diff --git a/aspnetcore/blazor/file-uploads.md b/aspnetcore/blazor/file-uploads.md index 6029e29e04c7..63fc9b6141ef 100644 --- a/aspnetcore/blazor/file-uploads.md +++ b/aspnetcore/blazor/file-uploads.md @@ -640,7 +640,7 @@ The following `FileUpload2` component: The following controller in the web API project saves uploaded files from the client. > [!IMPORTANT] -> The controller in this section is intended for use in a separate web API project from the Blazor app. The web API should [mitigate Cross-Site Request Forgery (XSRF/CSRF) attacks](xref:security/anti-request-forgery) if users are authenticated. +> The controller in this section is intended for use in a separate web API project from the Blazor app. The web API should [mitigate Cross-Site Request Forgery (XSRF/CSRF) attacks](xref:security/anti-request-forgery) if file upload users are authenticated. :::moniker range="= aspnetcore-6.0" @@ -655,8 +655,6 @@ Because the example uses the app's [environment](xref:blazor/fundamentals/enviro > [!WARNING] > The example saves files without scanning their contents, and the guidance in this article doesn't take into account additional security best practices for uploaded files. On staging and production systems, disable execute permission on the upload folder and scan files with an anti-virus/anti-malware scanner API immediately after upload. For more information, see . -> -> Additionally, the web API should [mitigate Cross-Site Request Forgery (XSRF/CSRF) attacks](xref:security/anti-request-forgery) if users are authenticated. `Controllers/FilesaveController.cs`: @@ -1028,8 +1026,6 @@ Because the example uses the app's [environment](xref:blazor/fundamentals/enviro > [!WARNING] > The example saves files without scanning their contents, and the guidance in this article doesn't take into account additional security best practices for uploaded files. On staging and production systems, disable execute permission on the upload folder and scan files with an anti-virus/anti-malware scanner API immediately after upload. For more information, see . -> -> Additionally, the web API should [mitigate Cross-Site Request Forgery (XSRF/CSRF) attacks](xref:security/anti-request-forgery) if users are authenticated. In the following example, update the shared project's namespace to match the shared project if a shared project is supplying the `UploadResult` class. @@ -1141,6 +1137,14 @@ In the preceding code, is called to g The server app must register controller services and map controller endpoints. For more information, see . + + ## Cancel a file upload A file upload component can detect when a user has cancelled an upload by using a when calling into the or . diff --git a/aspnetcore/blazor/forms/validation.md b/aspnetcore/blazor/forms/validation.md index 93f44a310dd5..fe6f9262039d 100644 --- a/aspnetcore/blazor/forms/validation.md +++ b/aspnetcore/blazor/forms/validation.md @@ -475,13 +475,7 @@ When validation messages are set in the component, they're added to the validato :::moniker range=">= aspnetcore-8.0" - - -> [!NOTE] -> For prior releases of .NET, this section was based on a hosted Blazor WebAssembly example, but hosted Blazor WebAssembly is no longer a project template in .NET 8. This section hasn't been updated to include new [.NET 8 antiforgery support features](xref:blazor/forms/index#antiforgery-support) and guidance for Blazor Web Apps. Article updates for this section are scheduled by [Add server validation with validator components for 8.0/BWA (dotnet/AspNetCore.Docs #30055)](https://github.com/dotnet/AspNetCore.Docs/issues/30055). You can inspect the prior guidance by selecting an earlier version of this article. +*This section is focused on Blazor Web App scenarios, but the approach for any type of app that uses server validation with web API adopts the same general approach.* :::moniker-end @@ -489,6 +483,8 @@ When validation messages are set in the component, they're added to the validato *This section is focused on hosted Blazor WebAssembly scenarios, but the approach for any type of app that uses server validation with web API adopts the same general approach.* +:::moniker-end + Server validation is supported in addition to client validation: * Process client validation in the form with the component. @@ -501,6 +497,22 @@ Basic validation is useful in cases where the form's model is defined within the The following example is based on: +:::moniker range=">= aspnetcore-8.0" + +* A Blazor Web App with interactive WebAssembly components created from the [Blazor Web App project template](xref:blazor/project-structure). +* The `Starship` model (`Starship.cs`) of the [Example form](xref:blazor/forms/input-components#example-form) section of the *Input components* article. +* The `CustomValidation` component shown in the [Validator components](#validator-components) section. + +Place the `Starship` model (`Starship.cs`) into a shared class library project so that both the client and server projects can use the model. Add or update the namespace to match the namespace of the shared app (for example, `namespace BlazorSample.Shared`). Since the model requires data annotations, confirm that the shared class library uses the shared framework or add the [`System.ComponentModel.Annotations`](https://www.nuget.org/packages/System.ComponentModel.Annotations) package to the shared project. + +[!INCLUDE[](~/includes/package-reference.md)] + +In the main project of the Blazor Web App, add a controller to process starship validation requests and return failed validation messages. Update the namespaces in the last `using` statement for the shared class library project and the `namespace` for the controller class. In addition to client and server data annotations validation, the controller validates that a value is provided for the ship's description (`Description`) if the user selects the `Defense` ship classification (`Classification`). + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + * A hosted Blazor WebAssembly [solution](xref:blazor/tooling#visual-studio-solution-file-sln) created from the [Blazor WebAssembly project template](xref:blazor/project-structure). The approach is supported for any of the secure hosted Blazor solutions described in the [hosted Blazor WebAssembly security documentation](xref:blazor/security/webassembly/index#implementation-guidance). * The `Starship` model (`Starship.cs`) of the [Example form](xref:blazor/forms/input-components#example-form) section of the *Input components* article. * The `CustomValidation` component shown in the [Validator components](#validator-components) section. @@ -511,10 +523,12 @@ Place the `Starship` model (`Starship.cs`) into the solution's **`Shared`** proj In the **:::no-loc text="Server":::** project, add a controller to process starship validation requests and return failed validation messages. Update the namespaces in the last `using` statement for the **`Shared`** project and the `namespace` for the controller class. In addition to client and server data annotations validation, the controller validates that a value is provided for the ship's description (`Description`) if the user selects the `Defense` ship classification (`Classification`). -The validation for the `Defense` ship classification only occurs on the server in the controller because the upcoming form doesn't perform the same validation client-side when the form is submitted to the server. server validation without client validation is common in apps that require private business logic validation of user input on the server. For example, private information from data stored for a user might be required to validate user input. Private data obviously can't be sent to the client for client validation. +:::moniker-end + +The validation for the `Defense` ship classification only occurs on the server in the controller because the upcoming form doesn't perform the same validation client-side when the form is submitted to the server. Server validation without client validation is common in apps that require private business logic validation of user input on the server. For example, private information from data stored for a user might be required to validate user input. Private data obviously can't be sent to the client for client validation. > [!NOTE] -> The `StarshipValidation` controller in this section uses Microsoft Identity 2.0. The Web API only accepts tokens for users that have the "`API.Access`" scope for this API. Additional customization is required if the API's scope name is different from `API.Access`. For a version of the controller that works with Microsoft Identity 1.0 and ASP.NET Core prior to version 5.0, see an earlier version of this article. +> The `StarshipValidation` controller in this section uses Microsoft Identity 2.0. The Web API only accepts tokens for users that have the "`API.Access`" scope for this API. Additional customization is required if the API's scope name is different from `API.Access`. > > For more information on security, see: > @@ -524,12 +538,8 @@ The validation for the `Defense` ship classification only occurs on the server i `Controllers/StarshipValidation.cs`: ```csharp -using System; -using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using Microsoft.Identity.Web.Resource; using BlazorSample.Shared; namespace BlazorSample.Server.Controllers; @@ -582,7 +592,7 @@ public class StarshipValidationController : ControllerBase } ``` -If using the preceding controller in a hosted Blazor WebAssembly app, update the namespace (`BlazorSample.Server.Controllers`) to match the app's controllers namespace. +Confirm or update the namespace of the preceding controller (`BlazorSample.Server.Controllers`) to match the app's controllers' namespace. When a model binding validation error occurs on the server, an [`ApiController`](xref:web-api/index) () normally returns a [default bad request response](xref:web-api/index#default-badrequest-response) with a . The response contains more data than just the validation errors, as shown in the following example when all of the fields of the `Starfleet Starship Database` form aren't submitted and the form fails validation: @@ -602,7 +612,7 @@ When a model binding validation error occurs on the server, an [`ApiController`] > [!NOTE] > To demonstrate the preceding JSON response, you must either disable the form's client validation to permit empty field form submission or use a tool to send a request directly to the server API, such as [Firefox Browser Developer](https://www.mozilla.org/firefox/developer/) or [Postman](https://www.postman.com). -If the server API returns the preceding default JSON response, it's possible for the client to parse the response in developer code to obtain the children of the `errors` node for forms validation error processing. It's inconvenient to write developer code to parse the file. Parsing the JSON manually requires producing a [`Dictionary>`](xref:System.Collections.Generic.Dictionary%602) of errors after calling . Ideally, the server API should only return the validation errors: +If the server API returns the preceding default JSON response, it's possible for the client to parse the response in developer code to obtain the children of the `errors` node for forms validation error processing. It's inconvenient to write developer code to parse the file. Parsing the JSON manually requires producing a [`Dictionary>`](xref:System.Collections.Generic.Dictionary%602) of errors after calling . Ideally, the server API should only return the validation errors, as the following example shows: ```json { @@ -615,6 +625,59 @@ If the server API returns the preceding default JSON response, it's possible for To modify the server API's response to make it only return the validation errors, change the delegate that's invoked on actions that are annotated with in the `Program` file. For the API endpoint (`/StarshipValidation`), return a with the . For any other API endpoints, preserve the default behavior by returning the object result with a new . +:::moniker range=">= aspnetcore-8.0" + +Add the namespace to the top of the `Program` file in the main project of the Blazor Web App: + +```csharp +using Microsoft.AspNetCore.Mvc; +``` + +In the `Program` file, add or update the following extension method and add the following call to : + +```csharp +builder.Services.AddControllersWithViews() + .ConfigureApiBehaviorOptions(options => + { + options.InvalidModelStateResponseFactory = context => + { + if (context.HttpContext.Request.Path == "/StarshipValidation") + { + return new BadRequestObjectResult(context.ModelState); + } + else + { + return new BadRequestObjectResult( + new ValidationProblemDetails(context.ModelState)); + } + }; + }); +``` + +If you're adding controllers to the main project of the Blazor Web App for the first time, map controller endpoints when you place the preceding code that registers services for controllers. The following example uses default controller routes: + +```csharp +app.MapDefaultControllerRoute(); +``` + +> [!NOTE] +> The preceding example explicitly registers controller services by calling to automatically [mitigate Cross-Site Request Forgery (XSRF/CSRF) attacks](xref:security/anti-request-forgery). If you merely use , anti-forgery is ***not*** enabled automatically. + +For more information on controller routing and validation failure error responses, see the following resources: + +* +* + +In the `.Client` project, add the `CustomValidation` component shown in the [Validator components](#validator-components) section. Update the namespace to match the app (for example, `namespace BlazorSample.Client`). + +In the `.Client` project, the `Starfleet Starship Database` form is updated to show server validation errors with help of the `CustomValidation` component. When the server API returns validation messages, they're added to the `CustomValidation` component's . The errors are available in the form's for display by the form's validation summary. + +In the following component, update the namespace of the shared project (`@using BlazorSample.Shared`) to the shared project's namespace. Note that the form requires authorization, so the user must be signed into the app to navigate to the form. + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + Add the namespace to the top of the `Program` file in the **:::no-loc text="Server":::** app: ```csharp @@ -642,7 +705,8 @@ builder.Services.AddControllersWithViews() }); ``` -For more information, see . +> [!NOTE] +> The preceding example explicitly registers controller services by calling to automatically [mitigate Cross-Site Request Forgery (XSRF/CSRF) attacks](xref:security/anti-request-forgery). If you merely use , anti-forgery is ***not*** enabled automatically. In the **:::no-loc text="Client":::** project, add the `CustomValidation` component shown in the [Validator components](#validator-components) section. Update the namespace to match the app (for example, `namespace BlazorSample.Client`). @@ -650,16 +714,18 @@ In the **:::no-loc text="Client":::** project, the `Starfleet Starship Database` In the following component, update the namespace of the **`Shared`** project (`@using BlazorSample.Shared`) to the shared project's namespace. Note that the form requires authorization, so the user must be signed into the app to navigate to the form. -`Starship10.razor`: +:::moniker-end - moniker-end moniker range="< aspnetcore-8.0" ---> - ```razor @page "/starship-10" @using System.Net @@ -860,7 +933,7 @@ moniker range="< aspnetcore-8.0"
-

+

@message
@@ -921,16 +994,17 @@ moniker range="< aspnetcore-8.0" } ``` - > [!NOTE] > As an alternative to the use of a [validation component](#validator-components), data annotation validation attributes can be used. Custom attributes applied to the form's model activate with the use of the component. When used with server validation, the attributes must be executable on the server. For more information, see . +:::moniker range="< aspnetcore-8.0" + > [!NOTE] > The server validation approach in this section is suitable for any of the hosted Blazor WebAssembly solution examples in this documentation set: >