【问题标题】:ASP.NET MVC 2 - How do I use an Interface as the Type for a Strongly Typed ViewASP.NET MVC 2 - 如何使用接口作为强类型视图的类型
【发布时间】:2010-03-25 12:23:30
【问题描述】:

我想将我的具体课程与我的观点分开。不使用强类型视图,我很好。我只是在控制器方法签名中使用了一个大参数列表,然后使用我的服务层工厂方法来创建我的具体对象。

这实际上对我来说很好,但它让我思考,玩了一会儿之后,我意识到控制器方法实际上不可能接受接口作为方法参数 - 因为它无法实例化它。也无法通过 IDE 使用接口创建强类型视图(这实际上是有道理的)。

所以我的问题。有没有办法告诉控制器如何使用我的服务层工厂方法实例化接口参数?

我想转换自:

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
[UrlRoute(Path = "Application/Edit/{id}")]
public ActionResult Edit(String id, String TypeCode, String TimeCode, String[] SelectedSchoolSystems,
            String PositionChoice1, String PositionChoice2, String PositionChoice3, String Reason, String LocationPreference,
            String AvailableDate, String RecipientsNotSelected, String RecipientsSelected) {

    //New blank app
    IApplication _application = ApplicationService.GetById(id);

类似

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
[UrlRoute(Path = "Application/Edit/{id}")]
public ActionResult Edit(String id, IApplication app) {

            //Don't need to do this anymore
            //IApplication _application = ApplicationService.GetById(id);

【问题讨论】:

  • 感谢大家的出色意见。巨大的帮助。
  • 已经好几个月了,但经过更多的编码 - 我开始意识到即使自定义模型绑定器可能是正确的答案,使用强类型视图模型对我来说效果最好。关键是视图模型经常与我的数据库对象不同。

标签: asp.net-mvc


【解决方案1】:

你需要视图模型层。

使用接口抽象出业务层实体可能有意义,但抽象 Web 应用程序特定实体没有多大意义(我猜在大多数情况下)。这将允许您针对实现进行编码。

并且尝试在不访问数据库的情况下从 Form 绑定实体也会带来很多麻烦。

【讨论】:

  • 也许我混合架构不当,但我已经有一个数据访问层和一个服务层 - 所以我将 MVC 站点视为表示层,我不想这样做创建只是我的数据层类的副本的视图模型。我是否误以为界面应该足够好?
  • @Rake36 对于某些情况可能就足够了。它总是取决于上下文。我只是说添加适当的视图模型可以轻松解决这个特定问题(但会通过视图模型和映射逻辑增加您的代码库)。
  • @Rake36 你可能会觉得这篇文章很有用 - bit.ly/9Bxpfj 我猜 - External coupling 是你遇到麻烦的原因。
  • 我读了这篇文章,我想我明白你的意思了。当视图本身确实可能需要它自己的具体类时,我正在努力维护 DRY。我想是时候写一些代码了……当我有有用的东西要分享时,我会回帖。
  • @Rake36 这里有一些关于视图模型的信息你可能会觉得有用 - stackoverflow.com/questions/2269144/…
【解决方案2】:

自定义模型绑定。只需让模型绑定器构建派生类的实例并将其作为接口返回即可。

另一方面,为什么?通常,您会为视图和控制器参数使用特定于视图的模型。每个视图/动作都有特定的模型需求。我可以理解为什么您可能希望从通用接口或抽象类派生它们 - 例如,您的母版页有一组可以使用的通用信息,但为什么特定操作需要接收数据作为抽象?难道它不能确切地知道它需要的数据类型并简单地使用正确的派生类作为参数类型吗?

【讨论】:

  • 控制器不知道要使用哪个派生类。只有服务层可以。我曾想过也许我可以继续创建特定于视图的模型,然后将它们用作服务层方法的参数。我试图避免在视图模型和我的具体类之间执行任何类型的映射。这有意义吗?
  • 我明白你在说什么,但我认为你走错了路。我发现当您拥有视图模型和数据模型时,事情会变得更好。我总是发现,我需要使用视图的额外数据来扩充我的数据模型,并将其封装在特定于视图的模型中似乎是最好的方法。
  • 谢谢。我将尝试这个想法以及自定义模型绑定方法。我会把我的结果发回这里。
【解决方案3】:

您可以编写一个自定义模型绑定器来实例化正确的类型:

public class MyModelBinder: DefaultModelBinder
{
    protected override object CreateModel(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext, 
        Type modelType
    )
    {
        return // ... instantiate your model here
    }
}

然后:

public ActionResult Edit(
    string id, 
    [ModelBinder(typeof(MyModelBinder))] IApplication app
)
{
   ...
}

【讨论】:

  • 到目前为止,我还没有仔细研究过自定义模型绑定器。谢谢你的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多