Is there a way to validate a model which is created inside web api controller?
Asked Answered
M

3

5

I have a controller where my PUT method uses multipart/form-data as content type and so I am getting the JSON and the mapped class thereby inside the controller.

Is there a way I could validate this model with respect to the annotations I have written in the model class while inside the controller?

public class AbcController : ApiController
{
    public HttpResponseMessage Put()
    {
        var fileForm = HttpContext.Current.Request.Form;
        var fileKey = HttpContext.Current.Request.Form.Keys[0];
        MyModel model = new MyModel();
        string[] jsonformat = fileForm.GetValues(fileKey);
        model = JsonConvert.DeserializeObject<MyModel>(jsonformat[0]);
     }
}

I need to validate "model" inside the controller. FYI, I have added required annotations to MyModel().

Maddox answered 3/11, 2016 at 10:57 Comment(0)
M
4

Manual model validation:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

class ModelValidator
{
    public static IEnumerable<ValidationResult> Validate<T>(T model) where T : class, new()
    {
        model = model ?? new T();

        var validationContext = new ValidationContext(model);

        var validationResults = new List<ValidationResult>();

        Validator.TryValidateObject(model, validationContext, validationResults, true);

        return validationResults;
    }
}
Muhammad answered 3/11, 2016 at 11:15 Comment(0)
M
3

Suppose you have defined models in Product class like :

namespace MyApi.Models
{
    public class Product
    {
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

and then inside controller just write:

 public class ProductsController : ApiController
    {
        public HttpResponseMessage Post(Product product)
        {
            if (ModelState.IsValid)
            {
                 return new HttpResponseMessage(HttpStatusCode.OK);
            }
         }
    }
Mcewen answered 3/11, 2016 at 11:5 Comment(4)
Thank you for the reply! But, this is not what I need as my model is not an input parameter of the function but it's taken from form data and then deserialized.Maddox
Please show me the sample code for both server(controller) and client side.Mcewen
Refer this one, I think it will be helpful for you to get more understanding regarding Validation and Submission of Form Data: asp.net/web-api/overview/advanced/sending-html-form-data-part-1Mcewen
I have added the code to my question. Client side code is not with me.Maddox
M
1

You can also use Fluent Validation to do this. https://docs.fluentvalidation.net/en/latest/aspnet.html

Your Model Class:

public class Customer 
{
  public int Id { get; set; }
  public string Surname { get; set; }
  public string Forename { get; set; }
  public decimal Discount { get; set; }
  public string Address { get; set; }
}

You would define a set of validation rules for this class by inheriting from AbstractValidator<Customer>:

using FluentValidation;

public class CustomerValidator : AbstractValidator<Customer> 
{
  RuleFor(customer => customer.Surname).NotNull();
  . . . etc;
}

To run the validator, instantiate the validator object and call the Validate method, passing in the object to validate.

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();

ValidationResult result = validator.Validate(customer);

The Validate method returns a ValidationResult object. This contains two properties:

IsValid - a boolean that says whether the validation succeeded. Errors - a collection of ValidationFailure objects containing details about any validation failures.

The following code would write any validation failures to the console from your controller or even from your service or repository:

using FluentValidation.Results; 

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();

ValidationResult results = validator.Validate(customer);

if(! results.IsValid) 
{
  foreach(var failure in results.Errors)
  {
    Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
  }
}

You can also inject the validator inside Program.cs , read here : https://docs.fluentvalidation.net/en/latest/di.html

Meitner answered 2/8, 2022 at 5:12 Comment(2)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewBeebe
Thanks for pointing this out, I have edited the answer and added relevant code.Meitner

© 2022 - 2024 — McMap. All rights reserved.