2016-12-05 7 views
2

Web APIを使用してWebサービスを構築しています。5. IModelBinderインターフェイスを拡張して複雑な型をパラメータとしてマップし、カスタムモデルバインダーを実装しています。バインディング部分は正常に動作しています。しかし、モデル検証は行われません。 ModelState.IsValidは常にtrueです。カスタムモデルバインダーでWeb API検証がトリガーされない

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. 
     } 
} 

私は明示的に()検証を呼び出すか、[FromUri]属性を使用する場合、ModelState.IsValidが正しく設定されています。

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

モデルバインダー内に検証部品を実装する必要があります。もしそうなら、私はどのように実装すべきですか?

+0

[SO回答](http://stackoverflow.com/questions/8668869/custom-model-binder-not-validating-model)の可能な複製。 –

+0

@MihailStancescu私はこの質問を見ました。それはDataAnnotationsでうまく動作します。 FluentValidationなどを使用すると動作しません。だから、ここに何かが欠けているようだ。 – sajith

答えて

2

私は答えを見つけました。次のようにデフォルトの検証プロセスは、カスタムモデルバインダーで呼び出すことができ、

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; 
     } 
} 

はあなたのサポートのためのみんなに感謝します。

+0

すばらしい、ありがとう.. – Pandiarajan

0

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); 
    } 
} 

ウェブ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>(); 
    } 
} 
+0

Web APIにDefaultModelBinderがありません。 DefaultModelBinderにはMVCが付属しています。 – sajith

+0

@sajith、MVC .NETアプリケーションでWeb APIを開発すると、 'DefaultModelBinder'が来るでしょう:) –

+0

Yah私はそれを知っています。しかし、問題は、PaginationModelBinder:DefaultModelBinderをコントローラの拡張ApiControllerで使用できないことです。 – sajith

関連する問題