简体   繁体   English

Web API验证不会触发自定义模型绑定器

[英]Web API Validation not trigger with custom model binder

I'm building Web Service with Web API 5. I'm implementing custom model binder by extending IModelBinder interface to map complex type as a parameter to action. 我正在使用Web API 5构建Web服务。我正在通过扩展IModelBinder接口来实现自定义模型绑定器,以将复杂类型映射为操作的参数。 The binding part is working fine. 绑定部分工作正常。 But Model validation does not occur. 但模型验证不会发生。 ModelState.IsValid is always true. ModelState.IsValid始终为true。

public class PagingParamsVM
{
        [Range(1, Int32.MaxValue, ErrorMessage = "Page must be at least 1")]
        public int? Page { get; set; }

        [Range(1, Int32.MaxValue, ErrorMessage = "Page size must be at least 1")]
        public int? PageSize { get; set; }
}

public class PaginationModelBinder : IModelBinder
{
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
              var model = (PagingParamsVM)bindingContext.Model ?? new PagingParamsVM();
              //model population logic
              .....

              bindingContext.Model = model;
              return true;
        }
}

public IEnumerable<NewsItemVM> Get([ModelBinder(typeof(PaginationModelBinder))]PagingParamsVM pegination)
{
            //Validate(pegination); //if I call this explicitly ModelState.IsValid is set correctly.
            var valid = ModelState.IsValid; //this is always true
}

public class ModelStateValidationActionFilter : ActionFilterAttribute
{
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var valid = actionContext.ModelState.IsValid //this is always true.
        }
}

If I call Validate() explicitly or use [FromUri] attribute, ModelState.IsValid is set correctly. 如果我显式调用Validate()或使用[FromUri]属性,则正确设置ModelState.IsValid。

public IEnumerable<NewsItemVM> Get([FromUri]PagingParamsVM pegination)
{
            var valid = ModelState.IsValid;
}

Should I implement validation part inside model binder. 我应该在模型绑定器中实现验证部分。 If so how should I implement? 如果是这样我应该如何实施?

I found an answer. 我找到了答案。 The default validation process can be invoked in custom model binder as follows, 可以在自定义模型绑定器中调用默认验证过程,如下所示,

public abstract class PaginationModelBinder : IModelBinder
{
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
              var model = (PagingParamsVM)bindingContext.Model ?? new PagingParamsVM();
              //model population logic
              .....

              bindingContext.Model = model;

              //following lines invoke default validation on model
              bindingContext.ValidationNode.ValidateAllProperties = true;
              bindingContext.ValidationNode.Validate(actionContext);

              return true;
        }
}

Thank you guys for your support. 谢谢你们的支持。

DefaultModelBinder.CreateModel should help you keep model state: DefaultModelBinder.CreateModel应该可以帮助您保持模型状态:

public class PaginationModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        if(modelType == typeof(PagingParamsVM))
        {
            var page = default(int?);
            var model = bindingContext.Model;
            var valueProvider = bindingContext.ValueProvider;
            var pageValue = valueProvider.GetValue("Page");
            var tmp = default(int);
            if(pageValue != null && int.TryParse(pageValue.AttemptedValue, out tmp))
            {
                page = tmp;
            }

            var pageSize = default(int?);
            var sizeValue = valueProvider.GetValue("PageSize");
            if(sizeValue != null && int.TryParse(sizeValue.AttemptedValue, out tmp))
            {
                pageSize = tmp;
            }
            return new PagingParamsVM { Page = page, PageSize = pageSize };
        }
        return base.CreateModel(controllerContext, bindingContext, modelType);
    }
}

A web api controller that uses the binder can be: 使用活页夹的web api控制器可以是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;

public class NewsItemController : ApiController
{
    public IEnumerable<NewsItemVM> Get([ModelBinder(typeof(PaginationModelBinder))]PagingParamsVM pegination)
    {
        //Validate(pegination); //if I call this explicitly ModelState.IsValid is set correctly.
        var valid = ModelState.IsValid; //this is always true
        return Enumerable.Empty<NewsItemVM>();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM