0

设置:

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

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

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

那么最好的方法是什么,或者它是不可能的?

我想我可以有一个基本的向导视图模型,我的所有向导视图模型都继承自(而不是直接实现IWizardModel)。

这行得通吗?

编辑(事后看来):

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

我认为我不能使用接口作为我的模型的原因是我做了以下事情:

@model IWizardModel // MyNamespace.MySpecificWizardModel

问题是右边的注释(我注释掉了旧模型)。

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

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

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

4

4 回答 4

2

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

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>

这似乎对我有用。我是否遗漏了您要求中的重要内容?

于 2012-11-01T17:58:30.383 回答
1

伊恩·加洛韦回答的附录:

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

想来想去,流程如下:

该模型:

可以说我有一个界面ISomeInterface

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

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

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

控制器和动作:

您可以将模型传递给视图,如下所示:

return View("MyView", MyModel);

看法:

作为MyModelimplements ISomeInterface,我可以在视图中写入:

@model ISomeInterface

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

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

在我的向导的情况下:

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

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

@model MyModel

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

wizard.cshtml通过在控制器的文件夹中包含一个实现,我仍然可以灵活地为每个向导进一步自定义。例如,如果我的向导上有一个验证码控件,并且它需要特定的 javascript 和样式文件,我可能想要这样做。

于 2012-11-03T12:40:36.973 回答
0

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

于 2012-11-01T16:54:26.950 回答
0

你可以用技巧做你想做的事:你可以创建WizardModel实现IWizardModel并包含InheritedWizardModeltype 属性的包装器模型IWizardModel

public class WizardModel: IWizardModel
{
    private IWizardModel _inheritedWizardModel{get;set;}

    //implementation IWizardModel
    public SomeType SomeIWizardProperty
    {
        get{return _inheritedWizardModel.SomeIWizardProperty;} 
        set{_inheritedWizardModel.SomeIWizardProperty = value;}
    }
}

并使用它

于 2012-11-01T17:12:56.097 回答