From 5f166a53b2b2fbfb9539c0870de33dd9659668e3 Mon Sep 17 00:00:00 2001 From: Chris Sainty Date: Fri, 8 May 2020 10:40:27 +0100 Subject: [PATCH] Added ability to disable assembly scanning and added some better exception catching --- Blazored.FluentValidation.sln | 4 +- README.md | 15 ++- azure-pipelines.yml | 4 +- samples/BlazorServer/App.razor | 10 ++ .../BlazorServer.csproj} | 2 +- .../Pages/Index.razor | 2 +- .../Pages/_Host.cshtml | 23 +++-- .../Program.cs | 2 +- .../Shared/MainLayout.razor | 0 .../Shared/NavMenu.razor | 0 .../Startup.cs | 8 +- .../_Imports.razor | 4 +- .../appsettings.Development.json | 0 .../appsettings.json | 0 .../wwwroot/css/bootstrap/bootstrap.min.css | 0 .../css/bootstrap/bootstrap.min.css.map | 0 .../wwwroot/css/open-iconic/FONT-LICENSE | 0 .../wwwroot/css/open-iconic/ICON-LICENSE | 0 .../wwwroot/css/open-iconic/README.md | 0 .../font/css/open-iconic-bootstrap.min.css | 0 .../open-iconic/font/fonts/open-iconic.eot | Bin .../open-iconic/font/fonts/open-iconic.otf | Bin .../open-iconic/font/fonts/open-iconic.svg | 0 .../open-iconic/font/fonts/open-iconic.ttf | Bin .../open-iconic/font/fonts/open-iconic.woff | Bin .../wwwroot/css/site.css | 19 ++++ .../wwwroot/favicon.ico | Bin samples/BlazorWebAssembly/App.razor | 10 ++ .../BlazorWebAssembly.csproj | 21 +++++ .../Pages/Index.razor | 0 .../Program.cs | 6 +- .../Shared/MainLayout.razor | 0 .../Shared/NavMenu.razor | 0 .../_Imports.razor | 7 +- .../wwwroot/css/bootstrap/bootstrap.min.css | 0 .../css/bootstrap/bootstrap.min.css.map | 0 .../wwwroot/css/open-iconic/FONT-LICENSE | 0 .../wwwroot/css/open-iconic/ICON-LICENSE | 0 .../wwwroot/css/open-iconic/README.md | 0 .../font/css/open-iconic-bootstrap.min.css | 0 .../open-iconic/font/fonts/open-iconic.eot | Bin .../open-iconic/font/fonts/open-iconic.otf | Bin .../open-iconic/font/fonts/open-iconic.svg | 0 .../open-iconic/font/fonts/open-iconic.ttf | Bin .../open-iconic/font/fonts/open-iconic.woff | Bin .../wwwroot/css/site.css | 19 ++++ samples/BlazorWebAssembly/wwwroot/index.html | 27 ++++++ samples/ClientSideBlazor/App.razor | 9 -- .../ClientSideBlazor/ClientSideBlazor.csproj | 21 ----- samples/ClientSideBlazor/wwwroot/index.html | 16 ---- samples/ServerSideBlazor/App.razor | 9 -- .../Shared/SharedModels/SharedModels.csproj | 2 +- .../Blazored.FluentValidation.csproj | 8 +- .../EditContextFluentValidationExtensions.cs | 86 ++++++++++++------ .../FluentValidationsValidator.cs | 3 +- 55 files changed, 227 insertions(+), 110 deletions(-) create mode 100644 samples/BlazorServer/App.razor rename samples/{ServerSideBlazor/ServerSideBlazor.csproj => BlazorServer/BlazorServer.csproj} (84%) rename samples/{ServerSideBlazor => BlazorServer}/Pages/Index.razor (96%) rename samples/{ServerSideBlazor => BlazorServer}/Pages/_Host.cshtml (66%) rename samples/{ServerSideBlazor => BlazorServer}/Program.cs (96%) rename samples/{ServerSideBlazor => BlazorServer}/Shared/MainLayout.razor (100%) rename samples/{ServerSideBlazor => BlazorServer}/Shared/NavMenu.razor (100%) rename samples/{ServerSideBlazor => BlazorServer}/Startup.cs (88%) rename samples/{ServerSideBlazor => BlazorServer}/_Imports.razor (81%) rename samples/{ServerSideBlazor => BlazorServer}/appsettings.Development.json (100%) rename samples/{ServerSideBlazor => BlazorServer}/appsettings.json (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/bootstrap/bootstrap.min.css (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/bootstrap/bootstrap.min.css.map (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/FONT-LICENSE (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/ICON-LICENSE (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/README.md (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/font/fonts/open-iconic.eot (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/font/fonts/open-iconic.otf (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/font/fonts/open-iconic.svg (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf (100%) rename samples/{ClientSideBlazor => BlazorServer}/wwwroot/css/open-iconic/font/fonts/open-iconic.woff (100%) rename samples/{ServerSideBlazor => BlazorServer}/wwwroot/css/site.css (86%) rename samples/{ServerSideBlazor => BlazorServer}/wwwroot/favicon.ico (100%) create mode 100644 samples/BlazorWebAssembly/App.razor create mode 100644 samples/BlazorWebAssembly/BlazorWebAssembly.csproj rename samples/{ClientSideBlazor => BlazorWebAssembly}/Pages/Index.razor (100%) rename samples/{ClientSideBlazor => BlazorWebAssembly}/Program.cs (70%) rename samples/{ClientSideBlazor => BlazorWebAssembly}/Shared/MainLayout.razor (100%) rename samples/{ClientSideBlazor => BlazorWebAssembly}/Shared/NavMenu.razor (100%) rename samples/{ClientSideBlazor => BlazorWebAssembly}/_Imports.razor (60%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/bootstrap/bootstrap.min.css (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/bootstrap/bootstrap.min.css.map (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/FONT-LICENSE (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/ICON-LICENSE (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/README.md (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/font/fonts/open-iconic.eot (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/font/fonts/open-iconic.otf (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/font/fonts/open-iconic.svg (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf (100%) rename samples/{ServerSideBlazor => BlazorWebAssembly}/wwwroot/css/open-iconic/font/fonts/open-iconic.woff (100%) rename samples/{ClientSideBlazor => BlazorWebAssembly}/wwwroot/css/site.css (85%) create mode 100644 samples/BlazorWebAssembly/wwwroot/index.html delete mode 100644 samples/ClientSideBlazor/App.razor delete mode 100644 samples/ClientSideBlazor/ClientSideBlazor.csproj delete mode 100644 samples/ClientSideBlazor/wwwroot/index.html delete mode 100644 samples/ServerSideBlazor/App.razor diff --git a/Blazored.FluentValidation.sln b/Blazored.FluentValidation.sln index 1320404..1542c55 100644 --- a/Blazored.FluentValidation.sln +++ b/Blazored.FluentValidation.sln @@ -5,9 +5,9 @@ VisualStudioVersion = 16.0.29006.145 MinimumVisualStudioVersion = 15.0.26124.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{D5C6DCA9-C2BD-4117-BCCC-19E36E8406AB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientSideBlazor", "samples\ClientSideBlazor\ClientSideBlazor.csproj", "{862C6849-B8FC-4062-AF84-A2DB37B9E43E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAssembly", "samples\BlazorWebAssembly\BlazorWebAssembly.csproj", "{862C6849-B8FC-4062-AF84-A2DB37B9E43E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerSideBlazor", "samples\ServerSideBlazor\ServerSideBlazor.csproj", "{00D9475F-C3D2-4784-82DE-E1D6991761EB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorServer", "samples\BlazorServer\BlazorServer.csproj", "{00D9475F-C3D2-4784-82DE-E1D6991761EB}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazored.FluentValidation", "src\Blazored.FluentValidation\Blazored.FluentValidation.csproj", "{12C755E1-0D7F-4D89-98C9-BD5AF560E0B5}" EndProject diff --git a/README.md b/README.md index fb654e9..42886aa 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ You can install from Nuget using the following command: Or via the Visual Studio package manger. -## Usage +## Basic Usage Start by add the following using statement to your root `_Imports.razor`. ```csharp @@ -55,3 +55,16 @@ You can then use it as follows within a `EditForm` component. } } ``` + +## Finding Validators +By default, the component will check for validators registered with DI first. If it can't find, any it will then try scanning the applications assemblies to find validators using reflection. + +You can control this behaviour using the `DisableAssemblyScanning` parameter. If you only wish the component to get validators from DI, set the value to `true` and assembly scanning will be skipped. + +```html + +``` + +You can find examples of different configurations in the sample projects. The Blazor Server project is configured to load validators from DI only. The Blazor WebAssembly project is setup to load validators using reflection. + +**Note:** When scanning assemblies the component will swallow any exceptions thrown by that process. This is to stop exceptions thrown by scanning third party dependencies crashing your app. \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c8e64d7..ca81bf8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,7 +2,7 @@ trigger: - master pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-latest' variables: buildConfiguration: 'Release' @@ -12,7 +12,7 @@ steps: displayName: 'Use .NET Core sdk' inputs: packageType: sdk - version: 3.1.100 + version: 3.1.201 installationPath: $(Agent.ToolsDirectory)/dotnet - task: NuGetToolInstaller@0 diff --git a/samples/BlazorServer/App.razor b/samples/BlazorServer/App.razor new file mode 100644 index 0000000..aa9ff24 --- /dev/null +++ b/samples/BlazorServer/App.razor @@ -0,0 +1,10 @@ + + + + + + +

Sorry, there's nothing at this address.

+
+
+
\ No newline at end of file diff --git a/samples/ServerSideBlazor/ServerSideBlazor.csproj b/samples/BlazorServer/BlazorServer.csproj similarity index 84% rename from samples/ServerSideBlazor/ServerSideBlazor.csproj rename to samples/BlazorServer/BlazorServer.csproj index a128ff3..bf96618 100644 --- a/samples/ServerSideBlazor/ServerSideBlazor.csproj +++ b/samples/BlazorServer/BlazorServer.csproj @@ -6,7 +6,7 @@ - + diff --git a/samples/ServerSideBlazor/Pages/Index.razor b/samples/BlazorServer/Pages/Index.razor similarity index 96% rename from samples/ServerSideBlazor/Pages/Index.razor rename to samples/BlazorServer/Pages/Index.razor index 2737ddb..32ea68e 100644 --- a/samples/ServerSideBlazor/Pages/Index.razor +++ b/samples/BlazorServer/Pages/Index.razor @@ -5,7 +5,7 @@
- +

diff --git a/samples/ServerSideBlazor/Pages/_Host.cshtml b/samples/BlazorServer/Pages/_Host.cshtml similarity index 66% rename from samples/ServerSideBlazor/Pages/_Host.cshtml rename to samples/BlazorServer/Pages/_Host.cshtml index 74fe3f9..d570595 100644 --- a/samples/ServerSideBlazor/Pages/_Host.cshtml +++ b/samples/BlazorServer/Pages/_Host.cshtml @@ -1,5 +1,5 @@ @page "/" -@namespace ServerSideBlazor.Pages +@namespace BlazorServer.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @@ -7,7 +7,7 @@ - Blazored FluentValidation - Blazor Server App + Blazored FluentValidation (Server) @@ -21,9 +21,20 @@ - - @(await Html.RenderComponentAsync(RenderMode.Server)) - - + + @(await Html.RenderComponentAsync(RenderMode.Server)) + +

+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + diff --git a/samples/ServerSideBlazor/Program.cs b/samples/BlazorServer/Program.cs similarity index 96% rename from samples/ServerSideBlazor/Program.cs rename to samples/BlazorServer/Program.cs index 47fe055..60d3921 100644 --- a/samples/ServerSideBlazor/Program.cs +++ b/samples/BlazorServer/Program.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace ServerSideBlazor +namespace BlazorServer { public class Program { diff --git a/samples/ServerSideBlazor/Shared/MainLayout.razor b/samples/BlazorServer/Shared/MainLayout.razor similarity index 100% rename from samples/ServerSideBlazor/Shared/MainLayout.razor rename to samples/BlazorServer/Shared/MainLayout.razor diff --git a/samples/ServerSideBlazor/Shared/NavMenu.razor b/samples/BlazorServer/Shared/NavMenu.razor similarity index 100% rename from samples/ServerSideBlazor/Shared/NavMenu.razor rename to samples/BlazorServer/Shared/NavMenu.razor diff --git a/samples/ServerSideBlazor/Startup.cs b/samples/BlazorServer/Startup.cs similarity index 88% rename from samples/ServerSideBlazor/Startup.cs rename to samples/BlazorServer/Startup.cs index 65cf813..fe0f4df 100644 --- a/samples/ServerSideBlazor/Startup.cs +++ b/samples/BlazorServer/Startup.cs @@ -1,10 +1,12 @@ +using FluentValidation; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using SharedModels; -namespace ServerSideBlazor +namespace BlazorServer { public class Startup { @@ -20,7 +22,9 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); - services.AddServerSideBlazor(c=>c.DetailedErrors = true); + services.AddServerSideBlazor(c => c.DetailedErrors = true); + + services.AddTransient, PersonValidator>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/samples/ServerSideBlazor/_Imports.razor b/samples/BlazorServer/_Imports.razor similarity index 81% rename from samples/ServerSideBlazor/_Imports.razor rename to samples/BlazorServer/_Imports.razor index d60f85c..86474da 100644 --- a/samples/ServerSideBlazor/_Imports.razor +++ b/samples/BlazorServer/_Imports.razor @@ -3,9 +3,9 @@ @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop -@using ServerSideBlazor -@using ServerSideBlazor.Shared +@using BlazorServer +@using BlazorServer.Shared @using SharedModels @using Blazored.FluentValidation \ No newline at end of file diff --git a/samples/ServerSideBlazor/appsettings.Development.json b/samples/BlazorServer/appsettings.Development.json similarity index 100% rename from samples/ServerSideBlazor/appsettings.Development.json rename to samples/BlazorServer/appsettings.Development.json diff --git a/samples/ServerSideBlazor/appsettings.json b/samples/BlazorServer/appsettings.json similarity index 100% rename from samples/ServerSideBlazor/appsettings.json rename to samples/BlazorServer/appsettings.json diff --git a/samples/ClientSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css b/samples/BlazorServer/wwwroot/css/bootstrap/bootstrap.min.css similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css rename to samples/BlazorServer/wwwroot/css/bootstrap/bootstrap.min.css diff --git a/samples/ClientSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css.map b/samples/BlazorServer/wwwroot/css/bootstrap/bootstrap.min.css.map similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css.map rename to samples/BlazorServer/wwwroot/css/bootstrap/bootstrap.min.css.map diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/FONT-LICENSE b/samples/BlazorServer/wwwroot/css/open-iconic/FONT-LICENSE similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/FONT-LICENSE rename to samples/BlazorServer/wwwroot/css/open-iconic/FONT-LICENSE diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/ICON-LICENSE b/samples/BlazorServer/wwwroot/css/open-iconic/ICON-LICENSE similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/ICON-LICENSE rename to samples/BlazorServer/wwwroot/css/open-iconic/ICON-LICENSE diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/README.md b/samples/BlazorServer/wwwroot/css/open-iconic/README.md similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/README.md rename to samples/BlazorServer/wwwroot/css/open-iconic/README.md diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css b/samples/BlazorServer/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css rename to samples/BlazorServer/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.eot b/samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.eot similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.eot rename to samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.eot diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.otf b/samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.otf similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.otf rename to samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.otf diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.svg b/samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.svg similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.svg rename to samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.svg diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf b/samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf rename to samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf diff --git a/samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.woff b/samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.woff similarity index 100% rename from samples/ClientSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.woff rename to samples/BlazorServer/wwwroot/css/open-iconic/font/fonts/open-iconic.woff diff --git a/samples/ServerSideBlazor/wwwroot/css/site.css b/samples/BlazorServer/wwwroot/css/site.css similarity index 86% rename from samples/ServerSideBlazor/wwwroot/css/site.css rename to samples/BlazorServer/wwwroot/css/site.css index 546810a..4a53920 100644 --- a/samples/ServerSideBlazor/wwwroot/css/site.css +++ b/samples/BlazorServer/wwwroot/css/site.css @@ -105,6 +105,25 @@ app { color: red; } +#blazor-error-ui { + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + 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; + } + @media (max-width: 767.98px) { .main .top-row { display: none; diff --git a/samples/ServerSideBlazor/wwwroot/favicon.ico b/samples/BlazorServer/wwwroot/favicon.ico similarity index 100% rename from samples/ServerSideBlazor/wwwroot/favicon.ico rename to samples/BlazorServer/wwwroot/favicon.ico diff --git a/samples/BlazorWebAssembly/App.razor b/samples/BlazorWebAssembly/App.razor new file mode 100644 index 0000000..aa9ff24 --- /dev/null +++ b/samples/BlazorWebAssembly/App.razor @@ -0,0 +1,10 @@ + + + + + + +

Sorry, there's nothing at this address.

+
+
+
\ No newline at end of file diff --git a/samples/BlazorWebAssembly/BlazorWebAssembly.csproj b/samples/BlazorWebAssembly/BlazorWebAssembly.csproj new file mode 100644 index 0000000..fa24362 --- /dev/null +++ b/samples/BlazorWebAssembly/BlazorWebAssembly.csproj @@ -0,0 +1,21 @@ + + + + netstandard2.1 + 3.0 + + + + + + + + + + + + + + + + diff --git a/samples/ClientSideBlazor/Pages/Index.razor b/samples/BlazorWebAssembly/Pages/Index.razor similarity index 100% rename from samples/ClientSideBlazor/Pages/Index.razor rename to samples/BlazorWebAssembly/Pages/Index.razor diff --git a/samples/ClientSideBlazor/Program.cs b/samples/BlazorWebAssembly/Program.cs similarity index 70% rename from samples/ClientSideBlazor/Program.cs rename to samples/BlazorWebAssembly/Program.cs index 11b77b5..4a6c021 100644 --- a/samples/ClientSideBlazor/Program.cs +++ b/samples/BlazorWebAssembly/Program.cs @@ -1,7 +1,7 @@ -using Microsoft.AspNetCore.Blazor.Hosting; -using System.Threading.Tasks; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -namespace ClientSideBlazor +namespace BlazorWebAssembly { public class Program { diff --git a/samples/ClientSideBlazor/Shared/MainLayout.razor b/samples/BlazorWebAssembly/Shared/MainLayout.razor similarity index 100% rename from samples/ClientSideBlazor/Shared/MainLayout.razor rename to samples/BlazorWebAssembly/Shared/MainLayout.razor diff --git a/samples/ClientSideBlazor/Shared/NavMenu.razor b/samples/BlazorWebAssembly/Shared/NavMenu.razor similarity index 100% rename from samples/ClientSideBlazor/Shared/NavMenu.razor rename to samples/BlazorWebAssembly/Shared/NavMenu.razor diff --git a/samples/ClientSideBlazor/_Imports.razor b/samples/BlazorWebAssembly/_Imports.razor similarity index 60% rename from samples/ClientSideBlazor/_Imports.razor rename to samples/BlazorWebAssembly/_Imports.razor index d2a1a5b..ad57959 100644 --- a/samples/ClientSideBlazor/_Imports.razor +++ b/samples/BlazorWebAssembly/_Imports.razor @@ -1,10 +1,13 @@ @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 ClientSideBlazor -@using ClientSideBlazor.Shared + +@using BlazorWebAssembly +@using BlazorWebAssembly.Shared @using SharedModels diff --git a/samples/ServerSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css b/samples/BlazorWebAssembly/wwwroot/css/bootstrap/bootstrap.min.css similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css rename to samples/BlazorWebAssembly/wwwroot/css/bootstrap/bootstrap.min.css diff --git a/samples/ServerSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css.map b/samples/BlazorWebAssembly/wwwroot/css/bootstrap/bootstrap.min.css.map similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/bootstrap/bootstrap.min.css.map rename to samples/BlazorWebAssembly/wwwroot/css/bootstrap/bootstrap.min.css.map diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/FONT-LICENSE b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/FONT-LICENSE similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/FONT-LICENSE rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/FONT-LICENSE diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/ICON-LICENSE b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/ICON-LICENSE similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/ICON-LICENSE rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/ICON-LICENSE diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/README.md b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/README.md similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/README.md rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/README.md diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.eot b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.eot similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.eot rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.eot diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.otf b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.otf similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.otf rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.otf diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.svg b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.svg similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.svg rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.svg diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf diff --git a/samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.woff b/samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.woff similarity index 100% rename from samples/ServerSideBlazor/wwwroot/css/open-iconic/font/fonts/open-iconic.woff rename to samples/BlazorWebAssembly/wwwroot/css/open-iconic/font/fonts/open-iconic.woff diff --git a/samples/ClientSideBlazor/wwwroot/css/site.css b/samples/BlazorWebAssembly/wwwroot/css/site.css similarity index 85% rename from samples/ClientSideBlazor/wwwroot/css/site.css rename to samples/BlazorWebAssembly/wwwroot/css/site.css index fa2c7f1..8d1c8a9 100644 --- a/samples/ClientSideBlazor/wwwroot/css/site.css +++ b/samples/BlazorWebAssembly/wwwroot/css/site.css @@ -96,6 +96,25 @@ app { color: red; } +#blazor-error-ui { + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + 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; + } + @media (max-width: 767.98px) { .main .top-row { display: none; diff --git a/samples/BlazorWebAssembly/wwwroot/index.html b/samples/BlazorWebAssembly/wwwroot/index.html new file mode 100644 index 0000000..c64a0df --- /dev/null +++ b/samples/BlazorWebAssembly/wwwroot/index.html @@ -0,0 +1,27 @@ + + + + + + Blazored FluentValidation (Wasm)) + + + + + + Loading... + +
+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + + + diff --git a/samples/ClientSideBlazor/App.razor b/samples/ClientSideBlazor/App.razor deleted file mode 100644 index 9f82992..0000000 --- a/samples/ClientSideBlazor/App.razor +++ /dev/null @@ -1,9 +0,0 @@ - - - - - -

Page not found

-

Sorry, but there's nothing here!

-
-
\ No newline at end of file diff --git a/samples/ClientSideBlazor/ClientSideBlazor.csproj b/samples/ClientSideBlazor/ClientSideBlazor.csproj deleted file mode 100644 index 2eae0c2..0000000 --- a/samples/ClientSideBlazor/ClientSideBlazor.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - netstandard2.1 - 7.3 - 3.0 - - - - - - - - - - - - - - - diff --git a/samples/ClientSideBlazor/wwwroot/index.html b/samples/ClientSideBlazor/wwwroot/index.html deleted file mode 100644 index 4ade202..0000000 --- a/samples/ClientSideBlazor/wwwroot/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Blazored FluentValidation - Blazor WebAssembly App - - - - - - Loading... - - - - diff --git a/samples/ServerSideBlazor/App.razor b/samples/ServerSideBlazor/App.razor deleted file mode 100644 index 9f82992..0000000 --- a/samples/ServerSideBlazor/App.razor +++ /dev/null @@ -1,9 +0,0 @@ - - - - - -

Page not found

-

Sorry, but there's nothing here!

-
-
\ No newline at end of file diff --git a/samples/Shared/SharedModels/SharedModels.csproj b/samples/Shared/SharedModels/SharedModels.csproj index 02a0859..f53442c 100644 --- a/samples/Shared/SharedModels/SharedModels.csproj +++ b/samples/Shared/SharedModels/SharedModels.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/Blazored.FluentValidation/Blazored.FluentValidation.csproj b/src/Blazored.FluentValidation/Blazored.FluentValidation.csproj index 27e3ea1..f389164 100644 --- a/src/Blazored.FluentValidation/Blazored.FluentValidation.csproj +++ b/src/Blazored.FluentValidation/Blazored.FluentValidation.csproj @@ -6,7 +6,7 @@ Blazored.FluentValidation Blazored.FluentValidation - 1.2.0 + 1.3.0 Chris Sainty A library for using FluentValidation with Blazor Copyright 2019 (c) Chris Sainty. All rights reserved. @@ -19,9 +19,9 @@ - - - + + + diff --git a/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs b/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs index c1a2344..cc76e81 100644 --- a/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs +++ b/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs @@ -12,12 +12,7 @@ public static class EditContextFluentValidationExtensions { private readonly static char[] separators = new[] { '.', '[' }; - public static EditContext AddFluentValidation(this EditContext editContext, IServiceProvider serviceProvider) - { - return AddFluentValidation(editContext, serviceProvider, null); - } - - public static EditContext AddFluentValidation(this EditContext editContext, IServiceProvider serviceProvider, IValidator validator) + public static EditContext AddFluentValidation(this EditContext editContext, IServiceProvider serviceProvider, bool disableAssemblyScanning, IValidator validator) { if (editContext == null) { @@ -27,41 +22,50 @@ public static EditContext AddFluentValidation(this EditContext editContext, ISer var messages = new ValidationMessageStore(editContext); editContext.OnValidationRequested += - (sender, eventArgs) => ValidateModel((EditContext)sender, messages, serviceProvider, validator); + (sender, eventArgs) => ValidateModel((EditContext)sender, messages, serviceProvider, disableAssemblyScanning, validator); editContext.OnFieldChanged += - (sender, eventArgs) => ValidateField(editContext, messages, eventArgs.FieldIdentifier, serviceProvider, validator); + (sender, eventArgs) => ValidateField(editContext, messages, eventArgs.FieldIdentifier, serviceProvider, disableAssemblyScanning, validator); return editContext; } - private static async void ValidateModel(EditContext editContext, ValidationMessageStore messages, IServiceProvider serviceProvider, IValidator validator = null) + private static async void ValidateModel(EditContext editContext, + ValidationMessageStore messages, + IServiceProvider serviceProvider, + bool disableAssemblyScanning, + IValidator validator = null) { - if (validator == null) + validator = validator ?? GetValidatorForModel(serviceProvider, editContext.Model, disableAssemblyScanning); + + if (validator is object) { - validator = GetValidatorForModel(serviceProvider, editContext.Model); - } + var validationResults = await validator.ValidateAsync(editContext.Model); - var validationResults = await validator.ValidateAsync(editContext.Model); + messages.Clear(); + foreach (var validationResult in validationResults.Errors) + { + var fieldIdentifier = ToFieldIdentifier(editContext, validationResult.PropertyName); + messages.Add(fieldIdentifier, validationResult.ErrorMessage); + } - messages.Clear(); - foreach (var validationResult in validationResults.Errors) - { - var fieldIdentifier = ToFieldIdentifier(editContext, validationResult.PropertyName); - messages.Add(fieldIdentifier, validationResult.ErrorMessage); + editContext.NotifyValidationStateChanged(); } - - editContext.NotifyValidationStateChanged(); } - private static async void ValidateField(EditContext editContext, ValidationMessageStore messages, FieldIdentifier fieldIdentifier, IServiceProvider serviceProvider, IValidator validator = null) + private static async void ValidateField(EditContext editContext, + ValidationMessageStore messages, + FieldIdentifier fieldIdentifier, + IServiceProvider serviceProvider, + bool disableAssemblyScanning, + IValidator validator = null) { var properties = new[] { fieldIdentifier.FieldName }; var context = new ValidationContext(fieldIdentifier.Model, new PropertyChain(), new MemberNameValidatorSelector(properties)); - validator = validator ?? GetValidatorForModel(serviceProvider, fieldIdentifier.Model); + validator = validator ?? GetValidatorForModel(serviceProvider, fieldIdentifier.Model, disableAssemblyScanning); - if (validator != null) + if (validator is object) { var validationResults = await validator.ValidateAsync(context); @@ -72,7 +76,7 @@ private static async void ValidateField(EditContext editContext, ValidationMessa } } - private static IValidator GetValidatorForModel(IServiceProvider serviceProvider, object model) + private static IValidator GetValidatorForModel(IServiceProvider serviceProvider, object model, bool disableAssemblyScanning) { var validatorType = typeof(IValidator<>).MakeGenericType(model.GetType()); if (serviceProvider != null) @@ -83,14 +87,19 @@ private static IValidator GetValidatorForModel(IServiceProvider serviceProvider, } } + if (disableAssemblyScanning) + { + return null; + } + var abstractValidatorType = typeof(AbstractValidator<>).MakeGenericType(model.GetType()); Type modelValidatorType = null; foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { - modelValidatorType = assembly.GetTypes().FirstOrDefault(t => t.IsSubclassOf(abstractValidatorType)); + modelValidatorType = IgnoreErrors(() => assembly.GetTypes().FirstOrDefault(t => t.IsSubclassOf(abstractValidatorType))); - if (modelValidatorType != null) + if (modelValidatorType is object && modelValidatorType != default) { break; } @@ -158,5 +167,30 @@ private static FieldIdentifier ToFieldIdentifier(EditContext editContext, string obj = newObj; } } + + /// + /// Runs an function that returns a value and ignores any Exceptions that occur. + /// Returns true or falls depending on whether catch was + /// triggered + /// + /// parameterless lamda that returns a value of T + /// Default value returned if operation fails + public static T IgnoreErrors(Func operation, T defaultValue = default(T)) + { + if (operation == null) + return defaultValue; + + T result; + try + { + result = operation.Invoke(); + } + catch + { + result = defaultValue; + } + + return result; + } } } diff --git a/src/Blazored.FluentValidation/FluentValidationsValidator.cs b/src/Blazored.FluentValidation/FluentValidationsValidator.cs index cca4ac4..56c9f4c 100644 --- a/src/Blazored.FluentValidation/FluentValidationsValidator.cs +++ b/src/Blazored.FluentValidation/FluentValidationsValidator.cs @@ -12,6 +12,7 @@ public class FluentValidationValidator : ComponentBase [CascadingParameter] EditContext CurrentEditContext { get; set; } [Parameter] public IValidator Validator { get; set; } + [Parameter] public bool DisableAssemblyScanning { get; set; } protected override void OnInitialized() @@ -23,7 +24,7 @@ protected override void OnInitialized() $"inside an {nameof(EditForm)}."); } - CurrentEditContext.AddFluentValidation(ServiceProvider, Validator); + CurrentEditContext.AddFluentValidation(ServiceProvider, DisableAssemblyScanning, Validator); } } }