通用控制器模型问题和多态性

建立:

我设计了一个向导(最初基于ProStream ASP.NET MVC 2中的Steve Sanderson向导)。

基本上,基本向导控制器的声明如下:

public abstract class WizardController<TModel> : Controller where TModel : class, IWizardModel, new()
{
   // Loads-n-loadsa-code
}

因此,为了实现我的向导,我需要声明我的向导控制器,如下所示:

[WizardOptions(StartLabel="Edit >>")]
public partial class EditFeeEarnerController : WizardController<MyApp.Models.MySpecificWizardModel>
{
     // small amounts of highly intuitive code
}

MyViewModel实现了IWizardModel

到现在为止还挺好。 这位精灵的作品非常漂亮,我对它也很满意,所以不要挂在那上面。

问题如下:

问题:

唯一的问题是我的向导对每个步骤都使用了部分视图,它们与视图( Wizard.cshtml )一起“缝合”在一起。

Wizard.cshtml 始终任何向导除了@model顶部声明,在我的例子:

@model MyApp.Models.MySpecificWizardModel

因此,在有20个向导的应用程序中,我有相同的文件出现20次。

绝对不是干的。

题:

我想在~/Views/Shared/Wizard.cshtml一个文件,并将其用于我的所有向导。 我不能这样做的原因是因为我只提前知道我的向导视图模型将继承自IWizardModel

我不能这样做:

@model IWizardModel

那么做到这一点的最好方法是什么,或者这是不可能的?

我想我可以有一个基本向导viewmodel,我所有的向导viewmodel继承(而不是直接实现IWizardModel )。

这会工作吗?

编辑(与事后的好处):

为了记录,我的问题是,我错误地认为使用接口作为我的模型,即@model IWizardModel不起作用。 正如Iain Galloway在他的回答中指出的那样,它解决了我的问题。

我认为我无法使用界面作为我的模型的原因是我做了以下操作:

@model IWizardModel // MyNamespace.MySpecificWizardModel

问题是对右侧的评论(我评论了旧模型)。

出于某种原因,评论产生了一个错误(与ViewEngine )。 在我的匆忙中,我只是假设你不能使用模型的接口。

正如奥尔德威尔所说:你的力量是伟大的,哦,延迟。

请参阅Iain Galloway的回答和我的附录。


我刚刚测试了以下内容: -

public interface IModel
{
    string Value { get; }
}

public class Foo : IModel
{
    public string Value { get; set; }
}

public class HomeController : Controller
{
    public ActionResult GenericView()
    {
        return View(new Foo() { Value = "Foo" });
    }
}

与GenericView.cshtml一起: -

@model MvcApplication1.Models.IModel

<h2>@Model.Value</h2>

这似乎为我工作。 我是否错过了一些重要的要求?


Iain Galloway的答案补遗:

Iain Galloway的回答是正确的,在视图中使用界面没有问题。

仔细思考,过程如下:

该模型:

可以说我有一个接口ISomeInterface

public interface ISomeInterface
{
    public int Step { get;set; }
}

我有一个实现ISomeInterface的模型类MyModel

public class MyModel : ISomeInterface
{
    public int Step { get;set; }
    public string Name { get;set; }
    public string Address { get;set; }
}

控制器和操作:

您可以按如下方式将模型传递给视图:

return View("MyView", MyModel);

视图:

MyModel实现ISomeInterface ,我可以在视图中写入:

@model ISomeInterface

应用多态性,因此视图可以访问由操作中的代码传入的MyModel上的所有属性,而不仅仅是视图声明的ISomeInterface属性。

这是我想要的。 它有效,所以Iain Galloway的答案被标记为正确。

在我的向导的情况下:

由于在一般情况下使用@model ISomeInterface,它也适用于我的向导。

然而,为了清楚起见,在每个步骤的部分视图 (并且仅在部分视图中)中,我留下了特定模型的声明,而不仅仅是它实现的接口。 即:

@model MyModel

作为使用@model的多态性的结果,我现在可以将wizard.cshtml文件移动到共享文件夹,这对于我的向导的整体DRYness性来说是一个很好的结果。

我仍然可以灵活地为每个向导定制我的wizard.cshtml ,方法是在控制器的文件夹中包含一个实现。 例如,如果我的向导有一个验证码控件,并且它需要特定的JavaScript和样式文件,我可能会这样做。


据我所知,你不能这样做。 原因是视图引擎静态编译强类型视图。 通过实现自己的视图引擎,可能会有一些非常先进的东西可以实现,但不太可能想要去做那么多工作来保存几行模板代码。

链接地址: http://www.djcxy.com/p/59757.html

上一篇: Generic Controller Model Issue and Polymorphism

下一篇: separate MVC project in to different projects?