2014-05-08 23 views
2

我想將控制器操作與系統的其他元素完全隔離,因爲它是對遺留代碼的重構,以便可以在系統的各個位置呈現操作。爲了隔離局部視圖模型中屬性名稱的任何重疊,我希望在表單名稱屬性前添加一個特定的值,並使用BindAttribute指示ModelBinder將模型屬性與適當的前綴表單字段進行匹配。在模型類上直接使用BindAttribute前綴

由於我有一些使用這個模型的動作,我希望我可以直接將[綁定]裝飾器放在模型類本身上,避免必須修飾每個模型參數。但是,這種方法似乎沒有註冊到活頁夾,所以我最終得到了未填充的屬性。另一方面,如果我將裝飾器移動到參數上,一切都很好。

BindAttribute的文檔表明它可以在類上使用。這不是一個受支持的方案嗎?

回答

5

你可以寫在相應的視圖模型的自定義模型綁定:

public class MyViewModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     bindingContext.ModelName = "some_prefix"; 
     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

,你可以在你的Application_Start註冊並關聯您的視圖模型:

ModelBinders.Binders.Add(typeof(MyViewModel), new MyViewModelBinder()); 

在這個例子中,我已經對前綴進行了硬編碼,但是您可以使模型綁定器更具通用性和可重用性,並考慮您可以用來裝飾您的視圖模型的BindAttribute

public class MyViewModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     // TODO: cache the result of this LINQ query to 
     // avoid using reflecting on each request. After all 
     // the metadata of the view model won't change at runtime 
     var bindAttribute = bindingContext 
      .ModelType 
      .GetCustomAttributes(typeof(BindAttribute), true) 
      .OfType<BindAttribute>() 
      .FirstOrDefault(); 

     bindingContext.ModelName = bindAttribute != null ? bindAttribute.Prefix : null; 
     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

,然後所有剩下的是裝飾用連接屬性您的視圖模型:

[Bind(Prefix = "some_prefix")] 
public class MyViewModel 
{ 
    public string Foo { get; set; } 
    public string Bar { get; set; } 
} 

,並要求正在該視圖模型的操作:

/someaction?some_prefix.foo=the_foo_value&some_prefix.bar=the_bar_value 
+0

感謝。我寧願不向系統中引入更多移動部件,因爲這不是OOtB支持的方案,所以我只裝飾參數並繼續前進。 – lsuarez

+0

在我做這件事之前,有一個簡單的問題是,將binder與基本模型類相關聯後,是否可以跨所有繼承它的模型重用,而無需在應用程序啓動時指定幾個這樣的指令? – lsuarez

+0

如果我沒有記錯,這將與基本模型和單一註冊一起工作,但我不是100%確定,應該測試。 –