TechBuddy.Extensions.Validation
1.1.2
dotnet add package TechBuddy.Extensions.Validation --version 1.1.2
NuGet\Install-Package TechBuddy.Extensions.Validation -Version 1.1.2
<PackageReference Include="TechBuddy.Extensions.Validation" Version="1.1.2" />
paket add TechBuddy.Extensions.Validation --version 1.1.2
#r "nuget: TechBuddy.Extensions.Validation, 1.1.2"
// Install TechBuddy.Extensions.Validation as a Cake Addin #addin nuget:?package=TechBuddy.Extensions.Validation&version=1.1.2 // Install TechBuddy.Extensions.Validation as a Cake Tool #tool nuget:?package=TechBuddy.Extensions.Validation&version=1.1.2
Validation Extension
Validation Extension is aiming to give you the opportunity to add FluentValidation in your WebAPI or HttpTrigger Azure Functions.
In this library we have extensions methods for two different object which are HttpRequest
for Azure Functions and IServiceCollection
for WebAPI projects.
<br>
Usages
Test Models Definition
public sealed class TestModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public sealed class TestValidator : AbstractValidator<TestModel>
{
public TestValidator()
{
RuleFor(i => i.Id).GreaterThan(0).WithMessage("{PropertyName} cannot be zero!");
RuleFor(i => i.Name).MinimumLength(3).WithMessage("{PropertyName} must be at least {MinLength} character");
}
}
<br>
HttpRequest Extensinon Usage
HttpRequest extensinon methods could be used in an Azure Function to validate the HttpRequest.Body by providing a model and IValidator<Model>
class that has validation rules.
Usage in Azure Functions 1
In Startup.cs
public override void Configure(IFunctionsHostBuilder builder)
{
var context = builder.GetContext();
builder.Services.AddTechBuddyValidator();
}
In Function File
private readonly IValidator<TestModel> testValidator;
public TestFunction(IValidator<TestModel> testValidator)
{
this.testValidator = testValidator;
}
[FunctionName("Function1")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] TestModel testModel)
{
var validationResult = testValidator.Validate(testModel); // FluentValidation Validate
if (!validationResult.IsValid)
return new BadRequestObjectResult(validationResult.Errors.Select(i => i.ErrorMessage));
return new OkObjectResult(testModel.Name);
}
<br>
Usage in Azure Functions 2
[FunctionName("Function2")]
public async Task<IActionResult> RunTest(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req)
{
var validationResult = await req.ValidateAsync<TestModel, TestValidator>(); // ValidationExtension Validate
if (!validationResult.IsValid)
return new BadRequestObjectResult(validationResult.ErrorMessages);
var testModel = await req.ReadFromJsonAsync<TestModel>();
return new OkObjectResult(testModel.Name);
}
<br> <br>
Usage in UnitTests
// Arrange
var model = new TestModel()
{
Id = 1,
Name = "Test"
};
var request = HttpRequestBuilder
.CreateRequest()
.SetBody(JsonSerializer.Serialize(model))
.ToRequest();
// Act
var result = await request.ValidateAsync<TestModel, TestValidator>();
// Assert
result.IsValid.Should().BeTrue();
result.Model.Should().BeEquivalentTo(model);
result.ErrorMessages.Should().BeNullOrEmpty();
WebAPI Extensinon Usage
In WebAPI, you can either use HttpRequest Extensions to validate your model manually as we do in Azure Functions, or you can inject all your validators into the system.
There are 3 different extension methods for IServiceCollection, where each has extra ValidationExtensionConfig
argument
// It gets the Assembly where TestValidation is in and start scanning for all IValidator<TModel> classes to inject
services.AddTechBuddyValidatorFromAssemblyContaining<TestValidator>();
// It gets the CallingAssembly which is where this method is called from(the WebApi) and start scanning for all IValidator<TModel> classes to inject
services.AddTechBuddyValidator();
// It uses the provided Assembly to start scanning for all IValidator<TModel> classes to inject
var assembly = Assembly.GetExecutingAssembly();
services.AddTechBuddyValidatorFromAssembly(assembly);
Important Config
ValidationExtensionConfig
can be provided as a parameter while adding the Validation into our system.
That config has UseModelProvider
method where you need to pass a class that is derived from IDefaultModelProvider
. This model will be used to return and object in ResponseBody once a validation error occured. So basically if there is a validation error, by using IDefaultModelProvider
you take the control and decide what you will return in response body. See the example below.
PS: BaseValidationErrorResponseModel is already in the Library, so you don't need to create it.
/// <summary>
/// BaseInvalidResponse Model
/// </summary>
public abstract class BaseValidationErrorResponseModel
{
/// <summary>
/// List of exceptions occured
/// </summary>
public IEnumerable<string> Errors { get; set; }
}
public class TestResponse : BaseValidationErrorResponseModel
{
public int HttpStatusCode { get; set; }
}
public class TestModelProvider : IDefaultModelProvider
{
public object GetModel(ModelStateDictionary.ValueEnumerable modelStateValues)
{
return new TestResponse()
{
Errors = modelStateValues.SelectMany(i => i.Errors).Select(i => string.Join(Environment.NewLine, i.ErrorMessage)),
HttpStatusCode = (int)HttpStatusCode.BadRequest
};
}
}
In your Startup.cs or Program.cs
builder.Services.AddTechBuddyValidator(config =>
{
config.UseModelProvider<TestModelProvider>();
});
So, if you configure your app like that, the result will be like below;
Request Body
{
"id": 0,
"Name": "Te"
}
Response
{
"httpStatusCode": 400,
"errors": [
"Id cannot be zero!",
"Name must be at least 3 character"
]
}
However, if you used the default(with out ModelProvider) implementation, the response would be like;
{
"errors": [
"Id cannot be zero!",
"Name must be at least 3 character"
]
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | 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. |
-
net6.0
- FluentValidation (>= 11.2.2)
- FluentValidation.AspNetCore (>= 11.2.2)
- FluentValidation.DependencyInjectionExtensions (>= 11.2.2)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0)
- Microsoft.AspNetCore.Mvc.Abstractions (>= 2.2.0)
- Microsoft.AspNetCore.Mvc.Core (>= 2.2.5)
- Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer (>= 5.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 3.1.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.