2012-01-11 1 views
3

Я понимаю, что ASP.NET MVC позволяет только POST-объектам выполнять действия в контроллере, где аргументы Action принимают размещенный объект как класс Concrete.ASP.NET MVC Проводка моделей к действию с интерфейсом

Есть ли способ обойти это, или хорошая альтернатива?

В моем случае, у меня есть действие, которое принимает интерфейс в качестве аргумента:

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

И для этого действия, у меня есть многочисленные взгляды, все сильно типизированных к объектам, реализующим IModel, все, что я хочу чтобы иметь возможность опубликовать этот метод.

Конечно, бег это дает мне ошибку:

Cannot create an instance of an interface

Есть ли хорошая работа вокруг этого? Или мне нужно создать метод Action для каждого и отправить их методу, подобному этому?

ответ

1

Хотя я упомянул об этом как о возможном решении в моем первоначальном вопросе, его решение, с которым я покончил, в конце концов, и мне действительно очень нравится это сейчас. Таким образом, мне не нужно было касаться реализации привязки по умолчанию для модели, и я думаю, что этот подход является более понятным и понятным подходом, чем то, о чем я изначально просил.

В случае, если неясно, почему я хотел пойти на этот подход, я добавил пример того, как я могу использовать это для своих преимуществ OO.

[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. Если у вас есть скрытое поле на стороне клиента или любой другой параметр, в котором вы можете определить, какой тип конкретного класса создать, вы можете просто создать собственное связующее устройство. Я считаю, что вы можете переопределить метод CreateModelDefaultModelBinder «s и использовать все другие встроенный в связывании функциональности

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

и модель связующих регистраций в global.asax

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

На самом деле, контроллеры и действия в MVC предназначены для быть тонким, а какой-то сервисный слой должен быть толстым. Поскольку логика действий, которую вы пытаетесь реализовать, может вскоре усложниться, я бы рекомендовал переместить ее в отдельный сервис.

+0

Спасибо за совет. Забавно, что вы упоминаете, как действия должны быть тонкими, так как именно поэтому я помещаю это здесь, так как в настоящее время существует много действий, выполняющих 100 строк строк кода операции. Я беру это и ставил его в службу, как вы предлагаете, и я оставил очень простые действия, которые все работают одинаково (только с разными моделями). На данный момент я продолжил создание Action для каждого конкретного класса, чтобы все они запустили мой абстрактный заводский метод. Теперь перед новой проблемой, где размещенный объект имеет значение null ... :( – Arkiliknam

 Смежные вопросы

  • Нет связанных вопросов^_^