2012-02-24 238 views
2

我需要這個的原因:在我的一個控制器中,我想以不同於應用程序其餘部分的方式綁定所有Decimal值。我不想註冊模型綁定在Global.asax中(通過ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());自定義模型綁定器來綁定嵌套屬性值

我試圖從DefaultModelBinder類派生並覆蓋其BindProperty方法,但只適用於模型實例的直接(不嵌套)十進制屬性。

我有以下的例子來說明我的問題:

namespace ModelBinderTest.Controllers 
{ 
    public class Model 
    { 
     public decimal Decimal { get; set; } 
     public DecimalContainer DecimalContainer { get; set; } 
    } 

    public class DecimalContainer 
    { 
     public decimal DecimalNested { get; set; } 
    } 

    public class DecimalModelBinder : DefaultModelBinder 
    { 
     protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
     { 
      if (propertyDescriptor.PropertyType == typeof (decimal)) 
      {     
       propertyDescriptor.SetValue(bindingContext.Model, 999M); 
       return; 
      } 

      base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
     } 
    } 

    public class TestController : Controller 
    { 

     public ActionResult Index() 
     { 
      Model model = new Model(); 
      return View(model); 
     } 

     [HttpPost] 
     public ActionResult Index([ModelBinder(typeof(DecimalModelBinder))] Model model) 
     { 
      return View(model); 
     } 

    } 
} 

該解決方案只設置ModelDecimal屬性爲999,但沒有做任何事情來DecimalContainerDecimalNested財產。我意識到這是因爲在我的DecimalModelBinderBindProperty重寫中調用base.BindProperty,但我不知道如何說服基類在處理小數屬性時使用我的模型活頁夾。

回答

1

你可以無條件申請模型綁定在你的Application_Start

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 

,然後有一個自定義的授權過濾器(是的,授權過濾器,因爲它模型綁定之前運行),將注入的HttpContext一定的價值可稍後通過模型綁定使用:

[AttributeUsage(AttributeTargets.Method)] 
public class MyDecimalBinderAttribute : ActionFilterAttribute, IAuthorizationFilter 
{ 
    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     filterContext.HttpContext.Items["_apply_decimal_binder_"] = true; 
    } 
} 

,然後在模型綁定測試是否含有HttpContext的應用befoire它的自定義值:

public class DecimalModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (controllerContext.HttpContext.Items.Contains("_apply_decimal_binder_")) 
     { 
      // The controller action was decorated with the [MyDecimalBinder] 
      // so we can proceed 
      return 999M; 
     } 

     // fallback to the default binder 
     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

現在,所有剩下的就是裝飾用自定義過濾器的控制器動作,使小數粘結劑:

[HttpPost] 
[MyDecimalBinder] 
public ActionResult Index(Model model) 
{ 
    return View(model); 
}