2012-12-03 93 views
0

基於用戶輸入,我想廢掉一個實體的某些屬性它獲取控制器的動作之前。 在粗的例子(真實模型是一個複雜得多),比方說,我的實體有一個定義,如果客戶端將被收費按月或按每兩週一BillingType屬性:如何使用自定義聯編程序來標準化用戶輸入?

public class BillingMethod 
{ 
    public int Id { get; set; } 
    public int BillingTypeValue { get; set; } 
    public BillingType BillingType 
    { 
     get 
     { 
      return (BillingType)BillingTypeValue; 
     } 
     set 
     { 
      BillingTypeValue = (int)value; 
     } 
    } 

    public int? DayOfMonth { get; set; } 
    public int? DayOfFirstFortnight { get; set; } 
    public int? DayOfSecondFortnight { get; set; } 
} 

public enum BillingType 
{ 
    Monthly, 
    Fortnightly 
} 

現在讓我們假設用戶選擇按月收費,然後將DayOfMonth屬性設置爲15.然後,他改變主意並每兩週設置一次結算類型,並設置兩個第一天屬性,並通過finnaly提交表單。 我需要的是一種方法來取消未使用的屬性(在本例中爲DayOfMonth),直到它到達Controller的Action。

我知道我可以從一個計費類型到另一個用戶的改變,或通過截獲表單的onsubmit事件通過javascript做到這一點。或者甚至在Action中,在將其保存到上下文之前,但我需要一種方法來做一次,並忘記它。

我認爲要做到這一點的最好辦法是通過使用自定義的模型綁定,但我沒有在任何經驗。我試圖創建一個新的ModelBindingContext,但我不知道如何獲取和解析新對象中的表單數據,所以我顯然需要一些方向。

回答

1

我設法使用自定義綁定器修改對象。首先我調用base.BindModel,然後在返回它之前修改屬性。

public class BillingMethodModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext cContext, ModelBindingContext bContext) 
    { 
     var newBillingMethod = (BillingMethod)base.BindModel(cContext, bContext); 
     var bType = newBillingMethod.BillingTypeValue; 
     if (bType == (int)BillingType.Monthly) 
     { 
      newBillingMethod.DayOfFirstFortnight = null; 
      newBillingMethod.DayOfSecondFortnight = null; 
     } 
     else 
     { 
      newBillingMethod.DayOfMonth = null; 
     } 

     return newBillingMethod; 
    } 
} 

,當然,加在Global.asax中的的Application_Start()的定製綁定:

ModelBinders.Binders.Add(typeof(BillingMethod), new BillingMethodModelBinder()); 

這對我來說真是棒極了,我等了一天左右接受這個答案之前以防萬一有人來更好的解決方案或指向我,而使用這種方法

1

我會小心自定義模型粘合劑這樣做。您遇到的一個問題是每個屬性都是單獨綁定的,而您對訂單沒有太多控制權。聽起來你需要在綁定完成後根據對象的狀態做出一些決定。

我可能會在這種情況下使用的行爲過濾器。請參閱:http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onactionexecuting(v=vs.98).aspx

public class BillMethodFilterAttribute : ActionFilterAttribute { 

    protected override void OnActionExecuting(ActionExecutingContext filterContext) { 
     base.OnActionExecuting(filterContext); 
      if (filterContext.Controller.ViewData.ModelMetadata.ModelType == typeof(BillingMethod)) { 
       var method = filterContext.Controller.ViewData.Model as BillingMethod; 
       if (method != null) { 
        //assign appropriately - binding is complete, you have full state of the object 
       } 
      } 
     }   
} 

[BillMethodFilter] 
public abstract class ProjectController : Controller { 


} 

public class SomeController : ProjectController { 

     public ActionResult SomeAction(BillingMethod method) { 
      //before this action runs, the BillMethodFilter should execute and your billing method will be fully initialized correctly 
     } 
} 
+0

我因子評分性質BindModel期間已經綁定我可能遇到的任何問題...但你說得對,我想結合後進行修改已完成。但是這個對象將被用在許多動作和不同的控制器中,所以我不確定動作過濾器... –

+1

您可以創建一個可重用的動作過濾器。創建一個從控制器繼承的基礎控制器,並將其用作所有控制器的基類(反正這通常是個好主意)。然後將您的過濾器屬性放在您的基礎控制器類上。這樣,所有控制器上的所有操作都應該運行你的過濾器。我會更新答案。 – Adam

相關問題