MiniValidationPlus 1.0.0
See the version list below for details.
dotnet add package MiniValidationPlus --version 1.0.0
NuGet\Install-Package MiniValidationPlus -Version 1.0.0
<PackageReference Include="MiniValidationPlus" Version="1.0.0" />
paket add MiniValidationPlus --version 1.0.0
#r "nuget: MiniValidationPlus, 1.0.0"
// Install MiniValidationPlus as a Cake Addin #addin nuget:?package=MiniValidationPlus&version=1.0.0 // Install MiniValidationPlus as a Cake Tool #tool nuget:?package=MiniValidationPlus&version=1.0.0
MiniValidationPlus
👉 with support of non-nullable reference types.
A minimalistic validation library built atop the existing features in .NET's System.ComponentModel.DataAnnotations
namespace. Adds support for single-line validation calls and recursion with cycle detection.
This project is fork of the original great repo MiniValidation from Damian Edwards and adds support of non-nullable reference types. Now validation works more like validation in model binding of ASP.NET Core MVC.
Supports .NET Standard 2.0 compliant runtimes.
Installation
Install the library from NuGet:
❯ dotnet add package MiniValidationPlus
ASP.NET Core 6+ Projects
If installing into an ASP.NET Core 6+ project, consider using the MinimalApis.Extensions package instead, which adds extensions specific to ASP.NET Core, including a validation endpoint filter for .NET 7 apps:
❯ dotnet add package MinimalApis.Extensions
Example usage
Validate an object
var widget = new Widget { Name = "" };
var isValid = MiniValidatorPlus.TryValidate(widget, out var errors);
class Widget
{
[Required, MinLength(3)]
public string Name { get; set; }
// Non-nullable reference types are required automatically
public string Category { get; set; }
public override string ToString() => Name;
}
Use services from validators
var widget = new Widget { Name = "" };
// Get your serviceProvider from wherever makes sense
var serviceProvider = ...
var isValid = MiniValidatorPlus.TryValidate(widget, serviceProvider, out var errors);
class Widget : IValidatableObject
{
[Required, MinLength(3)]
public string Name { get; set; }
// Non-nullable reference types are required automatically
public string Category { get; set; }
public override string ToString() => Name;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var disallowedNamesService = validationContext.GetService(typeof(IDisallowedNamesService)) as IDisallowedNamesService;
if (disallowedNamesService is null)
{
throw new InvalidOperationException($"Validation of {nameof(Widget)} requires an {nameof(IDisallowedNamesService)} instance.");
}
if (disallowedNamesService.IsDisallowedName(Name))
{
yield return new($"Cannot name a widget '{Name}'.", new[] { nameof(Name) });
}
}
}
Console app
using System.ComponentModel.DataAnnotations;
using MiniValidationPlus;
var nameAndCategory = args.Length > 0 ? args[0] : "";
var widgets = new List<Widget>
{
new Widget { Name = nameAndCategory, Category = nameAndCategory },
new WidgetWithCustomValidation { Name = nameAndCategory, Category = nameAndCategory }
};
foreach (var widget in widgets)
{
if (!MiniValidatorPlus.TryValidate(widget, out var errors))
{
Console.WriteLine($"{nameof(Widget)} has errors!");
foreach (var entry in errors)
{
Console.WriteLine($" {entry.Key}:");
foreach (var error in entry.Value)
{
Console.WriteLine($" - {error}");
}
}
}
else
{
Console.WriteLine($"{nameof(Widget)} '{widget}' is valid!");
}
}
class Widget
{
[Required, MinLength(3)]
public string Name { get; set; }
// Non-nullable reference types are required automatically
public string Category { get; set; }
public override string ToString() => Name;
}
class WidgetWithCustomValidation : Widget, IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.Equals(Name, "Widget", StringComparison.OrdinalIgnoreCase))
{
yield return new($"Cannot name a widget '{Name}'.", new[] { nameof(Name) });
}
}
}
❯ widget.exe
Widget has errors!
Name:
- The Widget name field is required.
Category:
- The Category field is required.
Widget has errors!
Name:
- The Widget name field is required.
Category:
- The Category field is required.
❯ widget.exe Ok
Widget has errors!
Name:
- The field Widget name must be a string or array type with a minimum length of '3'.
Widget has errors!
Name:
- The field Widget name must be a string or array type with a minimum length of '3'.
❯ widget.exe Widget
Widget 'Widget' is valid!
Widget has errors!
Name:
- Cannot name a widget 'Widget'.
❯ widget.exe MiniValidationPlus
Widget 'MiniValidationPlus' is valid!
Widget 'MiniValidationPlus' is valid!
Web app (.NET 6)
using System.ComponentModel.DataAnnotations;
using MiniValidationPlus;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World");
app.MapGet("/widgets", () =>
new[] {
new Widget { Name = "Shinerizer" },
new Widget { Name = "Sparklizer" }
});
app.MapGet("/widgets/{name}", (string name) =>
new Widget { Name = name });
app.MapPost("/widgets", (Widget widget) =>
!MiniValidatorPlus.TryValidate(widget, out var errors)
? Results.ValidationProblem(errors)
: Results.Created($"/widgets/{widget.Name}", widget));
app.MapPost("/widgets/custom-validation", (WidgetWithCustomValidation widget) =>
!MiniValidatorPlus.TryValidate(widget, out var errors)
? Results.ValidationProblem(errors)
: Results.Created($"/widgets/{widget.Name}", widget));
app.Run();
class Widget
{
[Required, MinLength(3)]
public string? Name { get; set; }
public override string? ToString() => Name;
}
class WidgetWithCustomValidation : Widget, IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.Equals(Name, "Widget", StringComparison.OrdinalIgnoreCase))
{
yield return new($"Cannot name a widget '{Name}'.", new[] { nameof(Name) });
}
}
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.ComponentModel.Annotations (>= 5.0.0)
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.