2010-10-25 75 views
1

经过这么多年使用ASP.Net,我仍然试图找出如何使用MVC实现相同的结果。MVC - 多个强类型的对象...在一个视图

我有一个控件强类型的东西的materpage。当我导航到不同的强类型模型的视图...并单击按钮执行某些操作时,我得到“传入字典的模型项目类型为Site.Models.RegisterModel”,但此字典需要模型“Site.Models.LogOnModel”类型的项目。

为了这个例子,我们可以使用VS 2010提供的Default MVC应用程序,让我们想象一下我想更改“LogonUserControl.ascx”,以便它告诉我登录的用户(因为它工作目前)或允许我从那里登录,向我显示用户名和密码的文本框(因此在这种情况下从主页)。

所以我采取了控制和强烈键入如下:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Gioby.Models.LogOnModel>" %> 
<% 
    if (Request.IsAuthenticated) { 
%> 
     Welcome <b><%: Page.User.Identity.Name %></b> 
     [ <%: Html.ActionLink("Log Off", "LogOff", "Account")%> ] 
<% 
    } 
    else { 
%> 
    <% using (Html.BeginForm()) { %> 
     <div id="logon"> 
       <div class="editor-label"> 
        <%: Html.LabelFor(m => m.UserName)%> 
        <%: Html.TextBoxFor(m => m.UserName)%> 
        <%: Html.ValidationMessageFor(m => m.UserName, "*") %> 
        <%: Html.LabelFor(m => m.Password)%> 
        <%: Html.PasswordFor(m => m.Password)%> 
        <%: Html.ValidationMessageFor(m => m.Password, "*") %> 
        <input type="submit" value="Log On" /> 
       </div> 

       <div class="editor-label"> 
        <%: Html.ActionLink("Register here", "Register", "Account")%> 
        <%: Html.CheckBoxFor(m => m.RememberMe, new { @class = "pad-left" })%> 
        <%: Html.LabelFor(m => m.RememberMe) %> 
       </div> 
     </div> 
    <% } %> 
<% 
    } 
%> 

然后在HomeController中,我添加了一个程序为:

[HttpPost] 
public ActionResult Index(LogOnModel model, string returnUrl) 
{ 
    if (ModelState.IsValid) 
    { 
      // ==>> Check Login against your DB 

      // Now check if param returnUrl is empty 
      if (!String.IsNullOrEmpty(returnUrl)) 
       return Redirect(returnUrl); 

      return RedirectToAction("Index", "Home"); 
    } 

    // If we got this far, something failed, redisplay form 
    return View(model); 
} 

我在主页上测试它...它的工作原理!

但是,当我浏览到“注册”视图(请记住,“LogonUserControl.ascx”位于里面的“母版”,因此从注册视图中可见)。

所以,当我点击注册按钮,我得到的错误: 传递到字典的模型产品类型Site.Models.RegisterModel的”,但这部词典需要类型Site.Models.LogOnModel的模型项目”。

问: 是否意味着我将永远无法在不同拼凑成一个看法?

比方说,我想写一个电子商务网站,并在主页上我想看到“最常用的标签”,“大多数购买的产品”,“本月产品”,“类别列表”......所有相同的视图,每个人都有自己的HTTP POST操作。

如果这可以使用MVC?

+1

您的'Register'控制器操作在哪里?你从上面的例子中忽略了它吗? – 2010-10-25 19:37:05

回答

0

如果我理解正确的问题,你必须使用相同的母版,但针对不同的ViewModels是强类型的两个视图。母版页可以包含也是强类型的部分视图,只要其预期的ViewModel与父视图相同即可。但是,如果您使用不同ViewModel类型的视图,它不知道该怎么做。

考虑以下几点:

<% Html.RenderPartial("LogOn") %> 

上面的代码隐式包括用于当前视图中的模型数据被呈现。这和你说过的完全一样:

<% Html.RenderPartial("LogOn", Model) %> 

所以这只会在Model是LogOnModel时才起作用。请记住,MasterPage实际上是View继承它的一部分,所以即使你把它放在MasterPage中,就好像你将相同的代码放在每个继承它的视图中。因此,如果您的视图模型与PartialView的模型不同,这将无法使用。另一种方法是使用继承来确保每个ViewModel都将包含Master Page所需的所有信息。这种方法详细描述在here

但是这种方法意味着您必须始终使用工厂来生成您的视图模型,并且每个视图模型必须知道它将使用哪个主页面。在我们的产品中,我们可以在同一视图中使用不同的主页面,具体取决于用户在何种模式下查看网站,因此将ViewModel与主页面的模式绑定是没有意义的。我们使用RenderAction方法完成您所描述的内容,该方法允许您呈现整个控制器操作,就好像它只是大视图的一部分。这种方法的一些优点在here讨论。

所以,现在你可以有你的母版包括任何你想要的小部分观点,但你建立这些意见的视图模型到一个单独的控制器的行动,负责该特定部分景观独立的逻辑:

<% Html.RenderAction("LogOnBox") %> 

行动:

public ActionResult LogOnBox() 
{ 
    LogOnModel model = GetLogOnModel(); 
    return PartialView("LogOnUserControl", model); 
} 

现在,不管什么型号的当前视图使用,您的主页面可以包括“本月产品”,“最常用的标签”,“大多数买产品”,“列表类别“等更好的是,页面的这些部分可以利用输出缓存,因此如果它们不经常更改,则不必在每次加载页面时都进行重新生成。

+0

不知道如何RenderAction会工作...你是否说使用它,而不是RenderPartial? RenderAction不是对方法的调用吗? – 2010-10-26 08:00:33

+0

@Filu:查看我更新的答案。 – StriplingWarrior 2010-10-26 15:48:28

+0

为了澄清,我们是否说每当我们创建一个局部视图(即一个Control.ascx),为了它的工作,它需要有他自己的ControllerFile.cs和自己的ModelFile.cs? 然后,如果我们使用RenderAction,则在View或MasterPage上我们要使用局部视图...应该有效。 如此理想的情况下,我们可以拥有一个包含10个局部视图的视图,每个视图都将指向他们自己的控制器和自己的模型,即使主视图属于另一个模型/控制器也是如此? 我仍然需要研究如何使用MVC与缓存,但肯定是在要做的事情列表。 – 2010-10-27 20:35:32

相关问题