From 3fcb15bf97d7b15aad60532ddd833290aec371f9 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Mon, 21 Sep 2026 09:50:32 -0400 Subject: [PATCH] Revert "Update Blazor form validation samples (#662)" This reverts commit 0ff725a4493e60dec85f51db3f76a33665447677. --- .../CustomFieldClassProvider.cs | 10 +- .../CustomFieldClassProvider2.cs | 5 +- .../BlazorSample.Client.csproj | 15 --- .../BlazorSample.Client/CustomValidation.cs | 50 -------- .../Pages/Starship10.razor | 114 ------------------ .../BlazorSample.Client/Program.cs | 12 -- .../Starship/ClientFormValidation.cs | 39 ------ .../Starship/IFormValidation.cs | 7 -- .../Starship/StarshipModel.cs | 25 ---- .../BlazorSample.Client/_Imports.razor | 9 -- .../BlazorSample/BlazorSample.csproj | 17 --- .../BlazorSample/Components/App.razor | 16 --- .../Components/Layout/MainLayout.razor | 5 - .../BlazorSample/Components/Routes.razor | 7 -- .../BlazorSample/Components/_Imports.razor | 9 -- .../BlazorSample/Program.cs | 47 -------- .../Starship/ServerFormValidation.cs | 75 ------------ .../BlazorSample/wwwroot/app.css | 1 - .../BlazorWebAppRemoteValidation.slnx | 5 - .../MinimalApiJwt/MinimalApiJwt.csproj | 13 -- .../MinimalApiJwt/Program.cs | 45 ------- .../MinimalApiJwt/StarshipModel.cs | 25 ---- .../BlazorSample.csproj | 9 -- .../Components/App.razor | 14 --- .../Components/AppManualStartup.razor | 7 -- .../Components/Pages/AsyncValidation.razor | 45 ------- .../Components/Pages/ClientValidation.razor | 34 ------ .../Components/Routes.razor | 5 - .../UsernameUniquenessValidator.razor | 71 ----------- .../Components/_Imports.razor | 9 -- 11.0/BlazorSample_BlazorWebApp/Program.cs | 18 --- .../Properties/launchSettings.json | 23 ---- .../Validation/RegistrationModel.cs | 9 -- .../Validation/ShipModel.cs | 12 -- .../Validation/StartsWithAttribute.cs | 42 ------- .../wwwroot/BlazorSample.lib.module.js | 14 --- .../wwwroot/js/custom-validation.js | 17 --- ...BlazorWebAppRemoteValidation.Client.csproj | 16 --- .../CustomValidation.razor | 53 -------- .../Layout/MainLayout.razor | 9 -- .../Layout/MainLayout.razor.css | 20 --- .../Models/StarshipModel.cs | 16 --- .../Pages/Home.razor | 88 -------------- .../Pages/NotFound.razor | 5 - .../Program.cs | 12 -- .../Routes.razor | 6 - .../Validation/ClientValidationExtensions.cs | 10 -- .../_Imports.razor | 10 -- .../BlazorWebAppRemoteValidation.slnx | 4 - .../BlazorWebAppRemoteValidation.csproj | 15 --- .../Components/App.razor | 20 --- .../Components/Pages/Error.razor | 40 ------ .../Components/_Imports.razor | 11 -- .../BlazorWebAppRemoteValidation/Program.cs | 48 -------- .../Properties/launchSettings.json | 14 --- .../appsettings.Development.json | 8 -- .../appsettings.json | 9 -- .../wwwroot/app.css | 38 ------ 11.0/BlazorWebAppRemoteValidation/README.md | 20 --- .../CustomFieldClassProvider.cs | 10 +- .../CustomFieldClassProvider2.cs | 5 +- .../CustomFieldClassProvider.cs | 10 +- .../CustomFieldClassProvider2.cs | 5 +- 63 files changed, 15 insertions(+), 1367 deletions(-) delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/BlazorSample.Client.csproj delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/CustomValidation.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Pages/Starship10.razor delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Program.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/ClientFormValidation.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/IFormValidation.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/StarshipModel.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/_Imports.razor delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/BlazorSample.csproj delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/App.razor delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Layout/MainLayout.razor delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Routes.razor delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/_Imports.razor delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/Program.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/Starship/ServerFormValidation.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorSample/wwwroot/app.css delete mode 100644 10.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx delete mode 100644 10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/MinimalApiJwt.csproj delete mode 100644 10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/Program.cs delete mode 100644 10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/StarshipModel.cs delete mode 100644 11.0/BlazorSample_BlazorWebApp/BlazorSample.csproj delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/App.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/AppManualStartup.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/Pages/AsyncValidation.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/Pages/ClientValidation.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/Routes.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/UsernameUniquenessValidator.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Components/_Imports.razor delete mode 100644 11.0/BlazorSample_BlazorWebApp/Program.cs delete mode 100644 11.0/BlazorSample_BlazorWebApp/Properties/launchSettings.json delete mode 100644 11.0/BlazorSample_BlazorWebApp/Validation/RegistrationModel.cs delete mode 100644 11.0/BlazorSample_BlazorWebApp/Validation/ShipModel.cs delete mode 100644 11.0/BlazorSample_BlazorWebApp/Validation/StartsWithAttribute.cs delete mode 100644 11.0/BlazorSample_BlazorWebApp/wwwroot/BlazorSample.lib.module.js delete mode 100644 11.0/BlazorSample_BlazorWebApp/wwwroot/js/custom-validation.js delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/BlazorWebAppRemoteValidation.Client.csproj delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/CustomValidation.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor.css delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Models/StarshipModel.cs delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/Home.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/NotFound.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Program.cs delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Routes.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Validation/ClientValidationExtensions.cs delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/_Imports.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.csproj delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/App.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/Pages/Error.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/_Imports.razor delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Program.cs delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Properties/launchSettings.json delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.Development.json delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.json delete mode 100644 11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/wwwroot/app.css delete mode 100644 11.0/BlazorWebAppRemoteValidation/README.md diff --git a/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs b/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs index 158681e1f..4adab8609 100644 --- a/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs +++ b/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs @@ -4,11 +4,7 @@ namespace BlazorSample; public class CustomFieldClassProvider : FieldCssClassProvider { - public override string GetFieldCssClass(EditContext editContext, - in FieldIdentifier fieldIdentifier) - { - var isValid = editContext.IsValid(fieldIdentifier); - - return isValid ? "validField" : "invalidField"; - } + public override string GetFieldCssClass( + EditContext editContext, in FieldIdentifier fieldIdentifier) => + editContext.IsValid(fieldIdentifier) ? "validField" : "invalidField"; } diff --git a/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs b/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs index e228f20a2..290dc8d3f 100644 --- a/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs +++ b/10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs @@ -9,9 +9,8 @@ public override string GetFieldCssClass(EditContext editContext, { if (fieldIdentifier.FieldName == "Name") { - var isValid = editContext.IsValid(fieldIdentifier); - - return isValid ? "validField" : "invalidField"; + return editContext.IsValid(fieldIdentifier) ? + "validField" : "invalidField"; } return string.Empty; diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/BlazorSample.Client.csproj b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/BlazorSample.Client.csproj deleted file mode 100644 index f3ce47fb2..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/BlazorSample.Client.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net10.0 - enable - enable - - - - - - - - - diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/CustomValidation.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/CustomValidation.cs deleted file mode 100644 index b19fefacb..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/CustomValidation.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Forms; - -namespace BlazorSample.Client; - -public class CustomValidation : ComponentBase -{ - private ValidationMessageStore? messageStore; - - [CascadingParameter] - private EditContext? CurrentEditContext { get; set; } - - protected override void OnInitialized() - { - if (CurrentEditContext is null) - { - throw new InvalidOperationException( - $"{nameof(CustomValidation)} requires a cascading " + - $"parameter of type {nameof(EditContext)}. " + - $"For example, you can use {nameof(CustomValidation)} " + - $"inside an {nameof(EditForm)}."); - } - - messageStore = new(CurrentEditContext); - - CurrentEditContext.OnValidationRequested += (s, e) => - messageStore?.Clear(); - CurrentEditContext.OnFieldChanged += (s, e) => - messageStore?.Clear(e.FieldIdentifier); - } - - public void DisplayErrors(IDictionary errors) - { - if (CurrentEditContext is not null) - { - foreach (var err in errors) - { - messageStore?.Add(CurrentEditContext.Field(err.Key), err.Value); - } - - CurrentEditContext.NotifyValidationStateChanged(); - } - } - - public void ClearErrors() - { - messageStore?.Clear(); - CurrentEditContext?.NotifyValidationStateChanged(); - } -} diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Pages/Starship10.razor b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Pages/Starship10.razor deleted file mode 100644 index b598ca568..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Pages/Starship10.razor +++ /dev/null @@ -1,114 +0,0 @@ -@page "/starship-10" -@using Microsoft.AspNetCore.Authorization -@using Microsoft.AspNetCore.Components.WebAssembly.Authentication -@using BlazorSample.Client.Starship -@attribute [Authorize] -@inject IFormValidation FormValidation -@inject ILogger Logger - -

Starfleet Starship Database

- -

New Ship Entry Form

- - - - - -
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- @message -
-
- -@code { - private CustomValidation? customValidation; - private bool disabled; - private string? message; - private string messageStyles = "visibility:hidden"; - - [SupplyParameterFromForm] - private StarshipModel? Model { get; set; } - - protected override void OnInitialized() => - Model ??= new() { ProductionDate = DateTime.UtcNow }; - - private async Task Submit(EditContext editContext) - { - customValidation?.ClearErrors(); - - try - { - var validationProblemDetails = - await FormValidation.ValidateStarshipFormAsync( - (StarshipModel)editContext.Model); - - if (validationProblemDetails?.Count > 0) - { - customValidation?.DisplayErrors(validationProblemDetails); - } - else - { - disabled = true; - messageStyles = "color:green"; - message = "The form has been processed."; - } - } - catch (AccessTokenNotAvailableException ex) - { - ex.Redirect(); - } - catch (Exception ex) - { - Logger.LogError(ex, "Form processing error."); - disabled = true; - messageStyles = "color:red"; - message = "There was an error processing the form."; - } - } -} diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Program.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Program.cs deleted file mode 100644 index 5ea5444e2..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Program.cs +++ /dev/null @@ -1,12 +0,0 @@ -using BlazorSample.Client.Starship; -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; - -var builder = WebAssemblyHostBuilder.CreateDefault(args); - -// The .Client project registers an HttpClient for HTTP POST requests to the Minimal API. -builder.Services.AddHttpClient(httpClient => -{ - httpClient.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress); -}); - -await builder.Build().RunAsync(); diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/ClientFormValidation.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/ClientFormValidation.cs deleted file mode 100644 index 11d5a98dd..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/ClientFormValidation.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Net.Http.Json; - -namespace BlazorSample.Client.Starship; - -internal sealed class ClientFormValidation(HttpClient httpClient) : IFormValidation -{ - public async Task> ValidateStarshipFormAsync( - StarshipModel starship) - { - Dictionary genericError = new() - { - { - "Validation Error", - ["An unexpected client error occurred during validation."] - } - }; - - try - { - using var response = await httpClient.PostAsJsonAsync( - "/starship-validation", starship); - - if (response.IsSuccessStatusCode) - { - var deserializedResponseContent = - await response.Content.ReadFromJsonAsync - >(); - - return deserializedResponseContent ?? genericError; - } - } - catch (Exception) - { - // Log the exception - } - - return genericError; - } -} diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/IFormValidation.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/IFormValidation.cs deleted file mode 100644 index 1d550e3eb..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/IFormValidation.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace BlazorSample.Client.Starship; - -public interface IFormValidation -{ - Task> ValidateStarshipFormAsync( - StarshipModel starship); -} diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/StarshipModel.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/StarshipModel.cs deleted file mode 100644 index abfc1ba1b..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Starship/StarshipModel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace BlazorSample.Client.Starship; - -public class StarshipModel -{ - [Required] - [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")] - public string? Id { get; set; } - - public string? Description { get; set; } - - [Required] - public string? Classification { get; set; } - - [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")] - public int MaximumAccommodation { get; set; } - - [Required] - [Range(typeof(bool), "true", "true", ErrorMessage = "Approval required.")] - public bool IsValidatedDesign { get; set; } - - [Required] - public DateTime ProductionDate { get; set; } -} diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/_Imports.razor b/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/_Imports.razor deleted file mode 100644 index 0bbc1c9d8..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/_Imports.razor +++ /dev/null @@ -1,9 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.AspNetCore.Components.WebAssembly.Http -@using Microsoft.JSInterop -@using BlazorSample.Client -@using BlazorSample.Client.Starship diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/BlazorSample.csproj b/10.0/BlazorWebAppRemoteValidation/BlazorSample/BlazorSample.csproj deleted file mode 100644 index 73173d45c..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/BlazorSample.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - net10.0 - enable - enable - - - - - - - - - - - diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/App.razor b/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/App.razor deleted file mode 100644 index 16c215390..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/App.razor +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Layout/MainLayout.razor b/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Layout/MainLayout.razor deleted file mode 100644 index 724fc91b6..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Layout/MainLayout.razor +++ /dev/null @@ -1,5 +0,0 @@ -@inherits LayoutComponentBase - -
- @Body -
diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Routes.razor b/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Routes.razor deleted file mode 100644 index bafa183bb..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/Routes.razor +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/_Imports.razor b/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/_Imports.razor deleted file mode 100644 index efcdfbd21..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Components/_Imports.razor +++ /dev/null @@ -1,9 +0,0 @@ -@using System.Net.Http -@using Microsoft.AspNetCore.Components.Authorization -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using static Microsoft.AspNetCore.Components.Web.RenderMode -@using BlazorSample -@using BlazorSample.Components -@using BlazorSample.Components.Layout diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Program.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample/Program.cs deleted file mode 100644 index 8d11d8aa3..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Program.cs +++ /dev/null @@ -1,47 +0,0 @@ -using BlazorSample.Client.Starship; -using BlazorSample.Components; -using BlazorSample.Starship; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents() - .AddInteractiveWebAssemblyComponents(); - -builder.Services.AddHttpClient(); -builder.Services.AddHttpContextAccessor(); - -// Register the server form validator for the IFormValidation interface. The server form -// validator is used on the server to call ValidateStarshipFormAsync for form validation. -builder.Services.AddScoped(); - -var app = builder.Build(); - -if (app.Environment.IsDevelopment()) -{ - app.UseWebAssemblyDebugging(); -} -else -{ - app.UseExceptionHandler("/Error", createScopeForErrors: true); - app.UseHsts(); -} - -app.UseHttpsRedirection(); -app.UseAntiforgery(); - -app.MapStaticAssets(); - -// Server-side endpoint that proxies form validation for components rendered on the server. -app.MapPost("/starship-validation", (IFormValidation formValidator, - StarshipModel model) => -{ - return formValidator.ValidateStarshipFormAsync(model); -}).RequireAuthorization(); - -app.MapRazorComponents() - .AddInteractiveServerRenderMode() - .AddInteractiveWebAssemblyRenderMode() - .AddAdditionalAssemblies(typeof(BlazorSample.Client._Imports).Assembly); - -app.Run(); diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Starship/ServerFormValidation.cs b/10.0/BlazorWebAppRemoteValidation/BlazorSample/Starship/ServerFormValidation.cs deleted file mode 100644 index de4d13e99..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/Starship/ServerFormValidation.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Net; -using System.Net.Http.Headers; -using System.Text.Json; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Mvc; -using BlazorSample.Client.Starship; - -namespace BlazorSample.Starship; - -internal sealed class ServerFormValidation( - IHttpContextAccessor httpContextAccessor, IHttpClientFactory httpClientFactory) - : IFormValidation -{ - public async Task> ValidateStarshipFormAsync( - StarshipModel starship) - { - Dictionary genericError = new() - { - { - "Validation Error", - ["An unexpected server error occurred during validation."] - } - }; - - try - { - if (httpContextAccessor.HttpContext is null) - { - throw new Exception("HttpContext not available"); - } - - var request = new HttpRequestMessage(HttpMethod.Post, - "https://localhost:7277/api-starship-validation") - { - Content = new StringContent(JsonSerializer.Serialize(starship), - System.Text.Encoding.UTF8, "application/json") - }; - - var accessToken = - await httpContextAccessor.HttpContext.GetTokenAsync("access_token"); - - request.Headers.Authorization = - new AuthenticationHeaderValue("Bearer", accessToken); - - using var httpClient = httpClientFactory.CreateClient(); - - var response = await httpClient.SendAsync(request); - - if (response?.StatusCode == HttpStatusCode.NoContent) - { - return new Dictionary(); - } - - if (response?.StatusCode == HttpStatusCode.BadRequest) - { - var content = await response.Content.ReadAsStringAsync(); - - var deserialized = - JsonSerializer.Deserialize( - content, - new JsonSerializerOptions(JsonSerializerDefaults.Web)); - - return deserialized?.Errors ?? genericError; - } - - return genericError; - } - catch (Exception) - { - // Log the exception - } - - return genericError; - } -} diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorSample/wwwroot/app.css b/10.0/BlazorWebAppRemoteValidation/BlazorSample/wwwroot/app.css deleted file mode 100644 index 1542a3a75..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorSample/wwwroot/app.css +++ /dev/null @@ -1 +0,0 @@ -main { font-family: sans-serif; } diff --git a/10.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx b/10.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx deleted file mode 100644 index f93270d21..000000000 --- a/10.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/MinimalApiJwt.csproj b/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/MinimalApiJwt.csproj deleted file mode 100644 index 04a85c4b9..000000000 --- a/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/MinimalApiJwt.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net10.0 - enable - enable - - - - - - - diff --git a/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/Program.cs b/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/Program.cs deleted file mode 100644 index d2e9e602d..000000000 --- a/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/Program.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MinimalApiJwt.Models; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddAuthentication().AddJwtBearer(); -builder.Services.AddAuthorization(); - -// Enables Microsoft.Extensions.Validation so data annotations on StarshipModel are -// validated before the endpoint handler runs. -builder.Services.AddValidation(); - -var app = builder.Build(); - -app.UseAuthentication(); -app.UseAuthorization(); - -// Remote validation endpoint. Data annotations on StarshipModel are validated by the -// framework. This handler adds the business rule that a 'Defense' ship requires a -// description, which is only validated on the server. -app.MapPost("/api-starship-validation", ( - StarshipModel model, ILogger logger) => -{ - Dictionary errors = []; - - if (model.Classification == "Defense" && string.IsNullOrEmpty(model.Description)) - { - errors.Add(nameof(model.Description), - ["For a 'Defense' ship, 'Description' is required."]); - } - - if (errors.Count > 0) - { - return Results.ValidationProblem( - errors: errors, - detail: "One or more validation errors occurred.", - instance: typeof(Program).Assembly.GetName().Name, - title: "Validation Errors", - type: "https://tools.ietf.org/html/rfc9110#section-15.5.1"); - } - - return Results.NoContent(); - -}).RequireAuthorization(); - -app.Run(); diff --git a/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/StarshipModel.cs b/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/StarshipModel.cs deleted file mode 100644 index 673a99ee8..000000000 --- a/10.0/BlazorWebAppRemoteValidation/MinimalApiJwt/StarshipModel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace MinimalApiJwt.Models; - -public class StarshipModel -{ - [Required] - [StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")] - public string? Id { get; set; } - - public string? Description { get; set; } - - [Required] - public string? Classification { get; set; } - - [Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")] - public int MaximumAccommodation { get; set; } - - [Required] - [Range(typeof(bool), "true", "true", ErrorMessage = "Approval required.")] - public bool IsValidatedDesign { get; set; } - - [Required] - public DateTime ProductionDate { get; set; } -} diff --git a/11.0/BlazorSample_BlazorWebApp/BlazorSample.csproj b/11.0/BlazorSample_BlazorWebApp/BlazorSample.csproj deleted file mode 100644 index 5086cb484..000000000 --- a/11.0/BlazorSample_BlazorWebApp/BlazorSample.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - net11.0 - enable - enable - - - diff --git a/11.0/BlazorSample_BlazorWebApp/Components/App.razor b/11.0/BlazorSample_BlazorWebApp/Components/App.razor deleted file mode 100644 index 3d5bc565e..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/App.razor +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/11.0/BlazorSample_BlazorWebApp/Components/AppManualStartup.razor b/11.0/BlazorSample_BlazorWebApp/Components/AppManualStartup.razor deleted file mode 100644 index 568eb1cf0..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/AppManualStartup.razor +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/11.0/BlazorSample_BlazorWebApp/Components/Pages/AsyncValidation.razor b/11.0/BlazorSample_BlazorWebApp/Components/Pages/AsyncValidation.razor deleted file mode 100644 index 8cea861fc..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/Pages/AsyncValidation.razor +++ /dev/null @@ -1,45 +0,0 @@ -@page "/async-validation" -@rendermode InteractiveServer - -@* Displays pending and faulted validation state for a field that's validated - asynchronously. *@ - -

Register

- - - - -
- - - - @if (editContext!.IsValidationPending(() => Model.Username)) - { - Checking… - } - else if (editContext.IsValidationFaulted(() => Model.Username)) - { - - Validation could not be completed. - - } -
- - @* Disabled while any field in the form has validation in flight. *@ - -
- -@code { - private EditContext? editContext; - - private RegistrationModel Model { get; set; } = new(); - - protected override void OnInitialized() => editContext = new(Model); - - private Task RegisterAsync() => Task.CompletedTask; -} diff --git a/11.0/BlazorSample_BlazorWebApp/Components/Pages/ClientValidation.razor b/11.0/BlazorSample_BlazorWebApp/Components/Pages/ClientValidation.razor deleted file mode 100644 index 6d87d46c0..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/Pages/ClientValidation.razor +++ /dev/null @@ -1,34 +0,0 @@ -@page "/client-validation" - -

Client-side validation

- -@if (submitted) -{ -

The form was submitted successfully.

-} - - - - - -
- - -
- - -
- -@code { - private bool submitted; - - [SupplyParameterFromForm] - private ShipModel? Model { get; set; } - - protected override void OnInitialized() => Model ??= new(); - - private void Submit() => submitted = true; -} diff --git a/11.0/BlazorSample_BlazorWebApp/Components/Routes.razor b/11.0/BlazorSample_BlazorWebApp/Components/Routes.razor deleted file mode 100644 index 06570ce63..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/Routes.razor +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/11.0/BlazorSample_BlazorWebApp/Components/UsernameUniquenessValidator.razor b/11.0/BlazorSample_BlazorWebApp/Components/UsernameUniquenessValidator.razor deleted file mode 100644 index 8474d855f..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/UsernameUniquenessValidator.razor +++ /dev/null @@ -1,71 +0,0 @@ -@implements IDisposable -@inject HttpClient Http - -@* A validator component that runs asynchronous validation, both when the whole form is - validated on submit and per field as the user edits the Username field. *@ - -@code { - [CascadingParameter] - private EditContext? CurrentEditContext { get; set; } - - [Parameter, EditorRequired] - public RegistrationModel Model { get; set; } = default!; - - private ValidationMessageStore? _messages; - - protected override void OnInitialized() - { - ArgumentNullException.ThrowIfNull(CurrentEditContext); - _messages = new ValidationMessageStore(CurrentEditContext); - CurrentEditContext.OnValidationRequested += OnValidationRequested; - CurrentEditContext.OnFieldChanged += OnFieldChanged; - } - - // Registers asynchronous work for the whole form. EditForm awaits it before invoking - // OnValidSubmit. - private void OnValidationRequested( - object? sender, ValidationRequestedEventArgs e) => - e.AddAsyncValidator(ValidateUsernameAsync); - - // Registers asynchronous work for a single field. A new registration supersedes and - // cancels any validation already in flight for the field. - private void OnFieldChanged(object? sender, FieldChangedEventArgs e) - { - if (e.FieldIdentifier.FieldName != nameof(RegistrationModel.Username)) - { - return; - } - - CurrentEditContext!.RegisterAsyncFieldValidator( - e.FieldIdentifier, - token => CheckAsync(e.FieldIdentifier, token)); - } - - private Task ValidateUsernameAsync(CancellationToken token) => - CheckAsync(CurrentEditContext!.Field(nameof(Model.Username)), token); - - private async Task CheckAsync(FieldIdentifier field, CancellationToken token) - { - _messages!.Clear(field); - - var available = await Http.GetFromJsonAsync( - $"api/usernames/available?value={Uri.EscapeDataString(Model.Username)}", - token); - - if (!available) - { - _messages.Add(field, "The username is already taken."); - } - - CurrentEditContext!.NotifyValidationStateChanged(); - } - - public void Dispose() - { - if (CurrentEditContext is not null) - { - CurrentEditContext.OnValidationRequested -= OnValidationRequested; - CurrentEditContext.OnFieldChanged -= OnFieldChanged; - } - } -} diff --git a/11.0/BlazorSample_BlazorWebApp/Components/_Imports.razor b/11.0/BlazorSample_BlazorWebApp/Components/_Imports.razor deleted file mode 100644 index 1de0bf6a0..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Components/_Imports.razor +++ /dev/null @@ -1,9 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using static Microsoft.AspNetCore.Components.Web.RenderMode -@using BlazorSample -@using BlazorSample.Components -@using BlazorSample.Validation diff --git a/11.0/BlazorSample_BlazorWebApp/Program.cs b/11.0/BlazorSample_BlazorWebApp/Program.cs deleted file mode 100644 index 5502cc4ca..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -using BlazorSample.Components; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents(); - -builder.Services.AddHttpClient(); -builder.Services.AddScoped(sp => - new HttpClient { BaseAddress = new Uri("https://localhost/") }); - -var app = builder.Build(); - -app.MapStaticAssets(); -app.MapRazorComponents() - .AddInteractiveServerRenderMode(); - -app.Run(); diff --git a/11.0/BlazorSample_BlazorWebApp/Properties/launchSettings.json b/11.0/BlazorSample_BlazorWebApp/Properties/launchSettings.json deleted file mode 100644 index 3b22ddddd..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Properties/launchSettings.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5030", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "https://localhost:7219;http://localhost:5030", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/11.0/BlazorSample_BlazorWebApp/Validation/RegistrationModel.cs b/11.0/BlazorSample_BlazorWebApp/Validation/RegistrationModel.cs deleted file mode 100644 index f35d5a155..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Validation/RegistrationModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace BlazorSample.Validation; - -public class RegistrationModel -{ - [Required] - public string Username { get; set; } = string.Empty; -} diff --git a/11.0/BlazorSample_BlazorWebApp/Validation/ShipModel.cs b/11.0/BlazorSample_BlazorWebApp/Validation/ShipModel.cs deleted file mode 100644 index d3f3fd853..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Validation/ShipModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace BlazorSample.Validation; - -// Model for the static SSR client-side validation sample. The StartsWith attribute -// contributes a client-side rule enforced in the browser before the form is submitted. -public class ShipModel -{ - [Required] - [StartsWith("NCC-")] - public string? Registry { get; set; } -} diff --git a/11.0/BlazorSample_BlazorWebApp/Validation/StartsWithAttribute.cs b/11.0/BlazorSample_BlazorWebApp/Validation/StartsWithAttribute.cs deleted file mode 100644 index 33d3b09ff..000000000 --- a/11.0/BlazorSample_BlazorWebApp/Validation/StartsWithAttribute.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Components.Forms; - -namespace BlazorSample.Validation; - -// A custom validation attribute that also contributes a client-side rule for static SSR -// forms. The rule name ('startswith') must match the validator registered on the client -// with Blazor.formValidation.addValidator. -public sealed class StartsWithAttribute : ValidationAttribute, IClientValidationRuleProvider -{ - private readonly string prefix; - - public StartsWithAttribute(string prefix) - { - this.prefix = prefix; - ErrorMessage = $"The value must start with '{prefix}'."; - } - - protected override ValidationResult? IsValid(object? value, - ValidationContext validationContext) - { - // Leave empty values to RequiredAttribute, matching the client-side validator. - if (value is not string text || text.Length == 0) - { - return ValidationResult.Success; - } - - if (!text.StartsWith(prefix, StringComparison.Ordinal)) - { - return new ValidationResult(ErrorMessage, [validationContext.MemberName!]); - } - - return ValidationResult.Success; - } - - public IEnumerable GetClientValidationRules() - { - yield return new ClientValidationRule( - "startswith", - new Dictionary { ["prefix"] = prefix }); - } -} diff --git a/11.0/BlazorSample_BlazorWebApp/wwwroot/BlazorSample.lib.module.js b/11.0/BlazorSample_BlazorWebApp/wwwroot/BlazorSample.lib.module.js deleted file mode 100644 index 12eb7e8b5..000000000 --- a/11.0/BlazorSample_BlazorWebApp/wwwroot/BlazorSample.lib.module.js +++ /dev/null @@ -1,14 +0,0 @@ -// A JavaScript initializer works with automatic or manual Blazor startup. The validation service -// is available when afterWebStarted runs, even if the current page contains no validated form. -export function afterWebStarted(blazor) { - blazor.formValidation.addValidator('startswith', (context) => { - const value = context.value; - - // An empty value is valid. Use [Required] to require a value. - if (!value) { - return { success: true }; - } - - return { success: value.startsWith(context.params.prefix) }; - }); -} diff --git a/11.0/BlazorSample_BlazorWebApp/wwwroot/js/custom-validation.js b/11.0/BlazorSample_BlazorWebApp/wwwroot/js/custom-validation.js deleted file mode 100644 index 0a3f7d4c3..000000000 --- a/11.0/BlazorSample_BlazorWebApp/wwwroot/js/custom-validation.js +++ /dev/null @@ -1,17 +0,0 @@ -function registerCustomValidators(blazor) { - blazor.formValidation.addValidator('startswith', (context) => { - const value = context.value; - - if (!value) { - return { success: true }; - } - - return { success: value.startsWith(context.params.prefix) }; - }); -} - -// Automatic startup initializes formValidation before this script runs. -// Manual startup calls registerCustomValidators after Blazor.start completes. -if (Blazor.formValidation) { - registerCustomValidators(Blazor); -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/BlazorWebAppRemoteValidation.Client.csproj b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/BlazorWebAppRemoteValidation.Client.csproj deleted file mode 100644 index 284c7b8d2..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/BlazorWebAppRemoteValidation.Client.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net11.0 - enable - enable - true - Default - true - - - - - - - diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/CustomValidation.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/CustomValidation.razor deleted file mode 100644 index c37be601c..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/CustomValidation.razor +++ /dev/null @@ -1,53 +0,0 @@ -@implements IDisposable - -@code { - [CascadingParameter] - private EditContext? CurrentEditContext { get; set; } - - private ValidationMessageStore _messages = default!; - - protected override void OnInitialized() - { - ArgumentNullException.ThrowIfNull(CurrentEditContext); - - _messages = new(CurrentEditContext); - CurrentEditContext.OnValidationRequested += HandleValidationRequested; - CurrentEditContext.OnFieldChanged += HandleFieldChanged; - } - - public void DisplayErrors(IDictionary errors) - { - foreach (var (fieldName, messages) in errors) - { - _messages.Add(CurrentEditContext!.Field(fieldName), messages); - } - - CurrentEditContext!.NotifyValidationStateChanged(); - } - - public void ClearErrors() - { - _messages.Clear(); - CurrentEditContext!.NotifyValidationStateChanged(); - } - - private void HandleValidationRequested( - object? sender, ValidationRequestedEventArgs e) => - ClearErrors(); - - private void HandleFieldChanged(object? sender, FieldChangedEventArgs e) - { - _messages.Clear(e.FieldIdentifier); - CurrentEditContext!.NotifyValidationStateChanged(); - } - - public void Dispose() - { - if (CurrentEditContext is not null) - { - CurrentEditContext.OnValidationRequested -= - HandleValidationRequested; - CurrentEditContext.OnFieldChanged -= HandleFieldChanged; - } - } -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor deleted file mode 100644 index 96fbbe6cc..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor +++ /dev/null @@ -1,9 +0,0 @@ -@inherits LayoutComponentBase - -@Body - -
- An unhandled error has occurred. - Reload - 🗙 -
diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor.css b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor.css deleted file mode 100644 index 60cec92d5..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Layout/MainLayout.razor.css +++ /dev/null @@ -1,20 +0,0 @@ -#blazor-error-ui { - color-scheme: light only; - background: lightyellow; - bottom: 0; - box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); - box-sizing: border-box; - display: none; - left: 0; - padding: 0.6rem 1.25rem 0.7rem 1.25rem; - position: fixed; - width: 100%; - z-index: 1000; -} - - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Models/StarshipModel.cs b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Models/StarshipModel.cs deleted file mode 100644 index b6363faab..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Models/StarshipModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Microsoft.Extensions.Validation; - -namespace BlazorWebAppRemoteValidation.Client.Models; - -[ValidatableType] -public sealed class StarshipModel -{ - [Required] - public string? Identifier { get; set; } - - [Required] - public string? Classification { get; set; } - - public string? Description { get; set; } -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/Home.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/Home.razor deleted file mode 100644 index b237522cf..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/Home.razor +++ /dev/null @@ -1,88 +0,0 @@ -@page "/" -@using System.Net -@using System.Net.Http.Json -@using BlazorWebAppRemoteValidation.Client.Models -@inject HttpClient Http - -Remote validation - -

Remote validation

- -

Local validation runs before the form calls the remote endpoint. The endpoint validates the model again and applies a private business rule that requires a description for defense ships.

- - - - - - -

- - -

- -

- - -

- -

- - -

- - -
- -@if (_accepted) -{ -

The server accepted the form.

-} - -@code { - private StarshipModel Model { get; } = new(); - private CustomValidation? _remoteErrors; - private bool _accepted; - - private async Task Submit() - { - _accepted = false; - - using var response = await Http.PostAsJsonAsync( - "api/starships/validate", Model); - - if (response.IsSuccessStatusCode) - { - _accepted = true; - return; - } - - if (response.StatusCode == HttpStatusCode.BadRequest) - { - var problem = await response.Content - .ReadFromJsonAsync() - ?? throw new InvalidOperationException( - "The validation response didn't contain a response body."); - - _remoteErrors!.DisplayErrors(problem.Errors); - return; - } - - response.EnsureSuccessStatusCode(); - } - - private sealed record ValidationProblemResponse( - Dictionary Errors); -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/NotFound.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/NotFound.razor deleted file mode 100644 index 091b6b8bc..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Pages/NotFound.razor +++ /dev/null @@ -1,5 +0,0 @@ -@page "/not-found" -@layout MainLayout - -

Not Found

-

Sorry, the content you are looking for does not exist.

diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Program.cs b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Program.cs deleted file mode 100644 index dbc58c3c8..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Program.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using BlazorWebAppRemoteValidation.Client.Validation; - -var builder = WebAssemblyHostBuilder.CreateDefault(args); - -// -builder.Services.AddScoped(sp => - new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); -// -builder.Services.AddClientModelValidation(); - -await builder.Build().RunAsync(); diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Routes.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Routes.razor deleted file mode 100644 index 105855d45..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Routes.razor +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Validation/ClientValidationExtensions.cs b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Validation/ClientValidationExtensions.cs deleted file mode 100644 index a87677a81..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/Validation/ClientValidationExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace BlazorWebAppRemoteValidation.Client.Validation; - -public static class ClientValidationExtensions -{ - public static IServiceCollection AddClientModelValidation( - this IServiceCollection services) => - services.AddValidation(); -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/_Imports.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/_Imports.razor deleted file mode 100644 index c6a97b714..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.Client/_Imports.razor +++ /dev/null @@ -1,10 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using static Microsoft.AspNetCore.Components.Web.RenderMode -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.JSInterop -@using BlazorWebAppRemoteValidation.Client -@using BlazorWebAppRemoteValidation.Client.Layout diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx deleted file mode 100644 index 3de70be30..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.slnx +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.csproj b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.csproj deleted file mode 100644 index 0e1b76406..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net11.0 - enable - enable - true - - - - - - - - diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/App.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/App.razor deleted file mode 100644 index 369684935..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/App.razor +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/Pages/Error.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/Pages/Error.razor deleted file mode 100644 index 3e5f5c98b..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/Pages/Error.razor +++ /dev/null @@ -1,40 +0,0 @@ -@page "/Error" -@using System.Diagnostics - -Error - -

Error.

-

An error occurred while processing your request.

- -@if (ShowRequestId) -{ -

- Request ID: @RequestId -

-} - -

Development Mode

-

- Swapping to Development environment will display more detailed information about the error that occurred. -

-

- The Development environment shouldn't be enabled for deployed applications. - It can result in displaying sensitive information from exceptions to end users. - For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development - and restarting the app. -

- -@code{ - [CascadingParameter] - private HttpContext? HttpContext { get; set; } - - [PersistentState] - public string? RequestId { get; set; } - - private bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - - protected override void OnInitialized() - { - RequestId ??= Activity.Current?.Id ?? HttpContext?.TraceIdentifier; - } -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/_Imports.razor b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/_Imports.razor deleted file mode 100644 index 6516c25c4..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Components/_Imports.razor +++ /dev/null @@ -1,11 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using static Microsoft.AspNetCore.Components.Web.RenderMode -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.JSInterop -@using BlazorWebAppRemoteValidation -@using BlazorWebAppRemoteValidation.Client -@using BlazorWebAppRemoteValidation.Components diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Program.cs b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Program.cs deleted file mode 100644 index 2740aa8ef..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Program.cs +++ /dev/null @@ -1,48 +0,0 @@ -using BlazorWebAppRemoteValidation.Components; -using BlazorWebAppRemoteValidation.Client.Models; -using BlazorWebAppRemoteValidation.Client.Validation; - -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. -builder.Services.AddRazorComponents() - .AddInteractiveWebAssemblyComponents(); -builder.Services.AddClientModelValidation(); -builder.Services.AddValidation(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (!app.Environment.IsDevelopment()) -{ - app.UseExceptionHandler("/Error", createScopeForErrors: true); -} -app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true); -app.MapStaticAssets(); - -// -app.MapPost("/api/starships/validate", (StarshipModel model) => -{ - Dictionary errors = []; - - if (model.Classification == "Defense" && - string.IsNullOrWhiteSpace(model.Description)) - { - errors[nameof(model.Description)] = - ["A defense ship requires a description."]; - } - - if (errors.Count > 0) - { - return Results.ValidationProblem(errors); - } - - return Results.NoContent(); -}); -// - -app.MapRazorComponents() - .AddInteractiveWebAssemblyRenderMode() - .AddAdditionalAssemblies(typeof(BlazorWebAppRemoteValidation.Client._Imports).Assembly); - -app.Run(); diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Properties/launchSettings.json b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Properties/launchSettings.json deleted file mode 100644 index 7d2665004..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/Properties/launchSettings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5257", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } - } diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.Development.json b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.json b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.json deleted file mode 100644 index 10f68b8c8..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/wwwroot/app.css b/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/wwwroot/app.css deleted file mode 100644 index 2db4212ee..000000000 --- a/11.0/BlazorWebAppRemoteValidation/BlazorWebAppRemoteValidation/wwwroot/app.css +++ /dev/null @@ -1,38 +0,0 @@ -h1:focus { - outline: none; -} - -.valid.modified:not([type=checkbox]) { - outline: 1px solid #26b050; -} - -.invalid { - outline: 1px solid #e50000; -} - -.validation-message { - color: #e50000; -} - -.blazor-error-boundary { - background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; - padding: 1rem 1rem 1rem 3.7rem; - color: white; -} - - .blazor-error-boundary::after { - content: "An error has occurred." - } - -.darker-border-checkbox.form-check-input { - border-color: #929292; -} - -.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder { - color: var(--bs-secondary-color); - text-align: end; -} - -.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder { - text-align: start; -} diff --git a/11.0/BlazorWebAppRemoteValidation/README.md b/11.0/BlazorWebAppRemoteValidation/README.md deleted file mode 100644 index 0b3b43b62..000000000 --- a/11.0/BlazorWebAppRemoteValidation/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Blazor Web App remote validation - -This sample uses an Interactive WebAssembly form and a Minimal API in the Blazor Web App host to demonstrate remote form validation. - -The form: - -1. Runs data annotations validation locally. -1. Sends locally valid input to the Minimal API. -1. Displays field-keyed errors returned by the endpoint. -1. Proceeds only when local and remote validation succeed. - -The endpoint validates data annotations before its handler runs and applies a private business rule in the handler. - -WebAssembly prerendering is disabled so the form's `HttpClient` dependency only needs to be registered in the `.Client` project. - -Run the sample from the solution directory: - -```dotnetcli -dotnet run --project BlazorWebAppRemoteValidation -``` diff --git a/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs b/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs index 158681e1f..4adab8609 100644 --- a/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs +++ b/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs @@ -4,11 +4,7 @@ namespace BlazorSample; public class CustomFieldClassProvider : FieldCssClassProvider { - public override string GetFieldCssClass(EditContext editContext, - in FieldIdentifier fieldIdentifier) - { - var isValid = editContext.IsValid(fieldIdentifier); - - return isValid ? "validField" : "invalidField"; - } + public override string GetFieldCssClass( + EditContext editContext, in FieldIdentifier fieldIdentifier) => + editContext.IsValid(fieldIdentifier) ? "validField" : "invalidField"; } diff --git a/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs b/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs index e228f20a2..290dc8d3f 100644 --- a/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs +++ b/8.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs @@ -9,9 +9,8 @@ public override string GetFieldCssClass(EditContext editContext, { if (fieldIdentifier.FieldName == "Name") { - var isValid = editContext.IsValid(fieldIdentifier); - - return isValid ? "validField" : "invalidField"; + return editContext.IsValid(fieldIdentifier) ? + "validField" : "invalidField"; } return string.Empty; diff --git a/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs b/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs index 158681e1f..4adab8609 100644 --- a/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs +++ b/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs @@ -4,11 +4,7 @@ namespace BlazorSample; public class CustomFieldClassProvider : FieldCssClassProvider { - public override string GetFieldCssClass(EditContext editContext, - in FieldIdentifier fieldIdentifier) - { - var isValid = editContext.IsValid(fieldIdentifier); - - return isValid ? "validField" : "invalidField"; - } + public override string GetFieldCssClass( + EditContext editContext, in FieldIdentifier fieldIdentifier) => + editContext.IsValid(fieldIdentifier) ? "validField" : "invalidField"; } diff --git a/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs b/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs index e228f20a2..290dc8d3f 100644 --- a/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs +++ b/9.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs @@ -9,9 +9,8 @@ public override string GetFieldCssClass(EditContext editContext, { if (fieldIdentifier.FieldName == "Name") { - var isValid = editContext.IsValid(fieldIdentifier); - - return isValid ? "validField" : "invalidField"; + return editContext.IsValid(fieldIdentifier) ? + "validField" : "invalidField"; } return string.Empty;