valit-stack/Valit

Integrating with ASP.NET Core

Closed this issue · 5 comments

I think that having the very solid Core library, we should start thinking about some integration projects and here comes the first one. I thought about creating new NuGet for the ASP.NET Core apps. The idea is simple, allow folks to kick off the validation before we start processing the particular action in the MVC6 controller, so the could use ModelState object to see the result (just like it was achieved before using the attributes). So to me the whole process should look as follows:

  1. Someone creates a new Model type
  2. Coresponding ModelValitator is created for type
  3. In Startup we register of valitators autmatically using UseValit() extension
  4. When the MVC controller receives the object in the body we can handle the validation like below:
public async Task DoSomethingAsync(Model model)
{
    if(! ModelState.IsValid)
    {
        return BadRequest(ModelState.Errors);
    }
    ....
}

That would be awesome 👍

Yes, that kind of middleware would be great! I will be happy to help.

@paw3lx great! We'll need to find out how to implement that :D

As far as I understand we need to create our custom ModelValidatorProvider which can be later added using:

services.AddMvc(options => options.ModelValidatorProviders.Add(...));

I found internal implementation for the data annotations on GitHub:

https://github.com/aspnet/Mvc/blob/64ffcfaa89177683a1fd08d5407a09f897bf97e0/src/Microsoft.AspNetCore.Mvc.DataAnnotations/Internal/DataAnnotationsModelValidatorProvider.cs

This won't be a simple task, but we should nailed this anyway :D

All right, after short break I finally got back to the project and I started doing this task localy. Surprisingly, I got first, working prototype done fairly quickly (about 30 minutes), so it's not that hard as I thought. However there are two issues that we need to overcome somehow:

  1. As far as I see #113 issue is required for this task since the whole validation is based on error messages. The rule is simple: any string message == model invalid. If there's no message returned then the model is valid. I checked that with Data Annotation and it uses default messages if it's not passed to the attribute. This basically means that we simply need default messages in Valit as well.

  2. One of the field returned in the validation result provided by ASP.NET Core is memberName which is then put into ModelState so the user knows which property is invalid. Currently we don't have this kind of the information in the IValitResult. This could be only guessed by messages but it's very unreliable solution since user could override it with the message not containing the name of the field. We need to come up with something more clever and ideally avoid another breaking change. But I'm afraid that it won't be that simple.

Since the Valit.Examples repo was empty I put there my prototype with example integration. Of course it works just for specific type but at least we'll know the direction of this integration :D