You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Components can capture and render additional attributes in addition to the component's declared parameters. Additional attributes can be captured in a dictionary and then applied to an element, called *splatting*, when the component is rendered using the [`@attributes`](xref:mvc/views/razor#attributes) Razor directive attribute. This scenario is useful for defining a component that produces a markup element that supports a variety of customizations. For example, it can be tedious to define attributes separately for an `<input>` that supports many parameters.
15
+
Components can capture and render additional attributes in addition to the component's declared parameters and fields. Additional attributes can be captured in a dictionary and then applied to an element, called *splatting*, when the component is rendered using the [`@attributes`](xref:mvc/views/razor#attributes) Razor directive attribute. This scenario is useful for defining a component that produces a markup element that supports a variety of customizations. For example, it can be tedious to define attributes separately for an `<input>` that supports many parameters or fields.
16
16
17
17
## Attribute splatting
18
18
19
19
In the following `Splat` component:
20
20
21
-
* The first `<input>` element (`id="useIndividualParams"`) uses individual component parameters.
21
+
* The first `<input>` element (`id="useIndividualParams"`) uses individual component fields.
22
22
* The second `<input>` element (`id="useAttributesDict"`) uses attribute splatting.
23
23
24
24
`Splat.razor`:
@@ -59,7 +59,7 @@ In the following `Splat` component:
59
59
60
60
:::moniker-end
61
61
62
-
The rendered `<input>` elements in the webpage are identical:
62
+
Except for `id`, the rendered `<input>` elements in the webpage have identical attributes:
63
63
64
64
```html
65
65
<inputid="useIndividualParams"
@@ -75,6 +75,8 @@ The rendered `<input>` elements in the webpage are identical:
75
75
size="50">
76
76
```
77
77
78
+
Although the preceding example uses fields for the first `<input>` element (`id="useIndividualParams"`), the same behavior applies when component parameters are used.
79
+
78
80
## Arbitrary attributes
79
81
80
82
To accept arbitrary attributes, define a [component parameter](xref:blazor/components/index#component-parameters) with the <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> property set to `true`:
@@ -88,7 +90,7 @@ To accept arbitrary attributes, define a [component parameter](xref:blazor/compo
88
90
89
91
The <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> property on [`[Parameter]`](xref:Microsoft.AspNetCore.Components.ParameterAttribute) allows the parameter to match all attributes that don't match any other parameter. A component can only define a single parameter with <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues>. The property type used with <xref:Microsoft.AspNetCore.Components.ParameterAttribute.CaptureUnmatchedValues> must be assignable from [`Dictionary<string, object>`](xref:System.Collections.Generic.Dictionary%602) with string keys. Use of [`IEnumerable<KeyValuePair<string, object>>`](xref:System.Collections.Generic.IEnumerable%601) or [`IReadOnlyDictionary<string, object>`](xref:System.Collections.Generic.IReadOnlyDictionary%602) are also options in this scenario.
90
92
91
-
The position of [`@attributes`](xref:mvc/views/razor#attributes) relative to the position of element attributes is important. When [`@attributes`](xref:mvc/views/razor#attributes) are splatted on the element, the attributes are processed from right to left (last to first). Consider the following example of a parent component that consumes a child component:
93
+
The position of [`@attributes`](xref:mvc/views/razor#attributes) relative to the position of element attributes is important. When [`@attributes`](xref:mvc/views/razor#attributes) are splatted on the rendered element, the attributes are processed from right to left (last to first) with the first attribute winning for any common attributes. Consider the following example of a parent component that consumes a child component, where the child sets an "`extra`" attribute and the parent component splats an "`extra`" attribute on the child component.
92
94
93
95
`AttributeOrderChild1.razor`:
94
96
@@ -176,13 +178,13 @@ The position of [`@attributes`](xref:mvc/views/razor#attributes) relative to the
176
178
177
179
:::moniker-end
178
180
179
-
The `AttributeOrderChild1` component's `extra` attribute is set to the right of [`@attributes`](xref:mvc/views/razor#attributes). The `AttributeOrderParent1` component's rendered `<div>` contains `extra="5"` when passed through the additional attribute because the attributes are processed right to left (last to first):
181
+
The `AttributeOrderChild1` component's `extra` attribute is set to the right of [`@attributes`](xref:mvc/views/razor#attributes). The `AttributeOrderParent1` component's rendered `<div>` contains `extra="5"` when passed through the additional attribute because the attributes are processed right to left (last to first) with the first "`extra`" attribute winning, which is the hard-coded `extra` HTML attribute of the `AttributeOrderParent1` component:
180
182
181
183
```html
182
184
<divextra="5" />
183
185
```
184
186
185
-
In the following example, the order of `extra` and [`@attributes`](xref:mvc/views/razor#attributes) is reversed in the child component's `<div>`:
187
+
In the following example, the order of `extra` and [`@attributes`](xref:mvc/views/razor#attributes) is reversed in the child component's `<div>`. In this scenario, the `AttributeOrderParent2` component's rendered `<div>` contains `extra="10"` when passed through the additional attribute because the first "`extra`" attribute processed is the splatted `extra` HTML attribute from the parent component.
186
188
187
189
`AttributeOrderChild2.razor`:
188
190
@@ -270,7 +272,7 @@ In the following example, the order of `extra` and [`@attributes`](xref:mvc/view
270
272
271
273
:::moniker-end
272
274
273
-
The `<div>` in the parent component's rendered webpage contains `extra="10"` when passed through the additional attribute:
275
+
The `<div>` in the parent component's rendered webpage contains `extra="10"`:
Copy file name to clipboardExpand all lines: aspnetcore/blazor/security/account-confirmation-and-password-recovery.md
+45-47Lines changed: 45 additions & 47 deletions
Original file line number
Diff line number
Diff line change
@@ -78,12 +78,18 @@ For more information, see <xref:security/app-secrets>.
78
78
79
79
[Azure Key Vault](https://azure.microsoft.com/products/key-vault/) provides a safe approach for providing the app's client secret to the app.
80
80
81
-
To create a key vault and set a secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. When you set the access policy for the secret in the **Access policies** panel:
81
+
To create a key vault and set a secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. For the example in this section, the secret name is "`EmailAuthKey`."
82
82
83
-
* Only the **Get** secret permission is required.
84
-
* Select the application as the **Principal** for the secret.
83
+
When establishing the key vault in the Entra or Azure portal:
85
84
86
-
Confirm in the Azure or Entra portal that the app has been granted access to the secret that you created for the email provider key.
85
+
* Configure the key vault to use Azure role-based access control (RABC). If you aren't operating on an [Azure Virtual Network](/azure/virtual-network/virtual-networks-overview), including for local development and testing, confirm that public access on the **Networking** step is **enabled** (checked). Enabling public access only exposes the key vault endpoint. Authenticated accounts are still required for access.
86
+
87
+
* Create an Azure Managed Identity (or add a role to the existing Managed Identity that you plan to use) with the **Key Vault Secrets User** role. Assign the Managed Identity to the Azure App Service that's hosting the deployment: **Settings** > **Identity** > **User assigned** > **Add**.
88
+
89
+
> [!NOTE]
90
+
> If you also plan to run an app locally with an authorized user for blob access using the [Azure CLI](/cli/azure/) or Visual Studio's Azure Service Authentication, add your developer Azure user account in **Access Control (IAM)** with the **Key Vault Secrets User** role. If you want to use the Azure CLI through Visual Studio, execute the `az login` command from the Developer PowerShell panel and follow the prompts to authenticate with the tenant.
91
+
92
+
To implement the code in this section, record the key vault URI (example: "`https://contoso.vault.azure.net/`", trailing slash required) and the secret name (example: "`EmailAuthKey`") from Azure when you create the key vault and secret.
87
93
88
94
> [!IMPORTANT]
89
95
> A key vault secret is created with an expiration date. Be sure to track when a key vault secret is going to expire and create a new secret for the app prior to that date passing.
@@ -93,74 +99,66 @@ Add the following `AzureHelper` class to the server project. The `GetKeyVaultSec
> The preceding example uses <xref:Azure.Identity.DefaultAzureCredential> to simplify authentication while developing apps that deploy to Azure by combining credentials used in Azure hosting environments with credentials used in local development. When moving to production, an alternative is a better choice, such as <xref:Azure.Identity.ManagedIdentityCredential>. For more information, see [Authenticate Azure-hosted .NET apps to Azure resources using a system-assigned managed identity](/dotnet/azure/sdk/authentication/system-assigned-managed-identity).
124
-
125
120
Where services are registered in the server project's `Program` file, obtain and bind the secret with [Options configuration](xref:fundamentals/configuration/options):
If you wish to control the environment where the preceding code operates, for example to avoid running the code locally because you've opted to use the [Secret Manager tool](#secret-manager-tool) for local development, you can wrap the preceding code in a conditional statement that checks the environment:
In the `AzureAd` section of `appsettings.json` in the server project, confirm the presence of the app's Entra ID `TenantId` and add the following `VaultUri` configuration key and value, if it isn't already present:
150
-
151
-
```json
152
-
"VaultUri": "{VAULT URI}"
153
-
```
129
+
else
130
+
{
131
+
// Local development and testing only
132
+
DefaultAzureCredentialOptionsoptions=new()
133
+
{
134
+
// Specify the tenant ID to use the dev credentials when running the app locally
135
+
// in Visual Studio.
136
+
VisualStudioTenantId="{TENANT ID}",
137
+
SharedTokenCacheTenantId="{TENANT ID}"
138
+
};
154
139
155
-
In the preceding example, the `{VAULT URI}` placeholder is the key vault URI. Include the trailing slash on the URI.
Configuration is used to facilitate supplying dedicated key vaults and secret names based on the app's environmental configuration files. For example, you can supply different configuration values for `appsettings.Development.json` in development, `appsettings.Staging.json` when staging, and `appsettings.Production.json` for the production deployment. For more information, see <xref:blazor/fundamentals/configuration>.
152
+
> [!NOTE]
153
+
> In non-Production environments, the preceding example uses <xref:Azure.Identity.DefaultAzureCredential> to simplify authentication while developing apps that deploy to Azure by combining credentials used in Azure hosting environments with credentials used in local development. For more information, see [Authenticate Azure-hosted .NET apps to Azure resources using a system-assigned managed identity](/dotnet/azure/sdk/authentication/system-assigned-managed-identity).
154
+
>
155
+
> The preceding example implies that the Managed Identity Client ID (`{MANAGED IDENTITY CLIENT ID}`), directory (tenant) ID (`{TENANT ID}`), and key vault URI (`{VAULT URI}`, example: `https://contoso.vault.azure.net/`, trailing slash required) are supplied by hard-coded values. Any or all of these values can be supplied from app settings configuration. For example, the following obtains the vault URI from the `AzureAd` node of an app settings file, and `vaultUri` can be used in the call to `GetKeyVaultSecret` in the preceding example:
0 commit comments