2012-01-11 61 views
3

我的理解是,ASP.NET MVC只允許您將控件中的對象發佈到動作,Action的參數接受發佈的對象作爲具體類。ASP.NET MVC將模型發佈到具有接口的動作

有沒有辦法解決這個問題,還是一個很好的選擇?

在我的情況,我有接受一個接口作爲參數的操作:

public ActionResult SaveAdjustment(IModel model) 
{ 
    switch (model.SubsetType) 
    { 
     // factory like usage 
    } 
} 

而對於這個動作,我有很多的看法,所有的強類型來實現IModel對象,所有這一切我想能夠發佈到這一個方法。

當然,運行該給我的錯誤:

Cannot create an instance of an interface

是否有一個很好的解決辦法這樣做呢?或者我需要爲每個方法創建一個Action方法,並將它們發送給像這樣的方法?

回答

1

儘管我在我的原始問題中提到過這是一個可能的解決方案,但它最終解決了我的問題,而且我現在非常喜歡它。這樣我就不需要觸摸模型的默認綁定實現,我認爲這種方法比我最初要求的方法更具可讀性/可理解性。

如果不清楚爲什麼我想採用這種方法,我已經添加了一個例子,說明如何使用它來實現面向對象的好處。

[HttpPost] 
    public ActionResult SaveModelA(ModelA model) 
    { 
     return SaveModel(model); 
    } 

    [HttpPost] 
    public ActionResult SaveModelB(ModelB model) 
    { 
     return SaveModel(model); 
    } 

    private ActionResult SaveModel(IModel model) 
    { 
     IExampleService exampleService; 
     IRequirements requirements; 

     switch (model.SubsetType) 
     { 
      case SubsetType.ModelA: 
       myService = new ModelAService(); 
       requirements = new ModelARequirements 
       { 
        ModelASpecificProperty = "example" 
       }; 
       break; 
      case SubsetType.ModelB: 
       myService = new ModelBService(); 
       requirements = new ModelBRequirements 
       { 
        ModelBSpecificProperty1 = "example", 
        ModelBSpecificProperty2 = "example2", 
        ModelBSpecificProperty3 = "example3" 
       }; 
       break;     
      default: 
       throw new InvalidEnumArgumentException(); 
     } 

     var serviceResonse = exampleService.ExecuteExample(model, requirements); 

     return RedirectToAction("Index", new 
     { 
      ExampleData = serviceResponse.ExampleDate 
     }); 
    } 

如果它不是在代碼中明確:

ModelA : IModel 
ModelB : IModel 
ModelARequirements : IModelRequirements 
ModelBRequirements : IModelRequirements 
ModelAService : IExampleService 
ModelBService : IExampleService 

// and IModel defines a property SubsetType SubsetType { get; } 
3

MVC通常在從Request.Form發佈時綁定模型,即name = value對的集合。之所以在默認實現中不支持綁定接口或抽象類是顯而易見的 - mvc無法確定從name = value對創建哪個具體類。如果您在客戶端有隱藏字段,或者您可以通過其中任何其他參數來確定要創建哪種類型的具體類,則可以簡單地創建自定義模型聯編程序。我相信你可以重寫DefaultModelBinderCreateModel方法和重複使用的所有其他建在Global.asax的

ModelBinders.Binders.Add(typeof(IModel?), new IModelModelBinder()); 

實際上綁定功能

public class IModelModelBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType) 
    { 
     //Create and return concrete instance 
    } 
} 

而且模型綁定的註冊,在MVC控制器和行動是爲了很薄,某種服務層應該很厚。由於您嘗試實施的行動邏輯可能會很快變得複雜,因此我建議您將其轉移到單獨的服務中。

+0

謝謝你的建議。有趣的是你提到了行動應該如何變薄,因爲這正是我爲什麼要這樣做的原因,因爲目前有很多行動都是在做100行的行爲代碼。我把它放到一個像你所建議的服務中,並且留下了非常簡單的操作,這些操作都以相同的方式運行(只是使用不同的模型)。現在我已經爲每個具體的類做了一個Action,讓他們都像方法一樣運行我的抽象工廠。現在面臨一個新的問題,發佈的對象爲空...... :( – Arkiliknam 2012-01-11 17:11:15

相關問題