【问题标题】:MVC3 Multiple Models - single pageMVC3 多个模型 - 单页
【发布时间】:2012-01-15 02:46:24
【问题描述】:

我有一个 _layout 页面,它有一个登录框(部分视图),并且该视图有它自己的模型。所以控制器看起来像这样:

        public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(LoginModel loginModel)
    {
        if(ModelState.IsValid)
        {
            var g = new GallaryImage();
            var user = g.LoginUser(loginModel.Username, loginModel.Password);
            if(user != null) 
            {
                FormsAuthentication.SetAuthCookie(user.username, false);
                return RedirectToAction("Index", "Home");
            }
            ModelState.AddModelError("", "Invalid Username/Password");
        }
        return View(loginModel);
    }

但只要我的主要内容页面需要模型,我的 Web 应用程序就会失败,因为登录框需要 LoginModel 类型,但我的内容页面正在发送不同的模型:

这是我的主索引屏幕的 GET 方法:

 public ActionResult Index()
    {
        IndexModel model = new IndexModel();
        var g = new GallaryService.GallaryImage();
        var i = g.GetRandomImage();

        if (i != null)
            model.RandomImageUrl = "~/Images/Watermarks/" + i.filename;
            return View(model);
    }

所以,我的主要内容页面有一个 IndexModel,但我的部分视图有一个 LoginModel。当我尝试运行它时,我得到一个错误:

“传入字典的模型项的类型为‘GalleryPresentation.Models.IndexModel’,但此字典需要‘GalleryPresentation.Models.LoginModel’类型的模型项。”

我该如何处理 - 我的 _layout 需要登录框的模型。

根据要求,这里是登录框 cshtml 文件。

    @using GalleryPresentation.Models
@model LoginModel

<script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>
@using (Html.BeginForm("index", "Account", FormMethod.Post))
{
    <table class="smallBox">
        <tr>
            <td>@Html.LabelFor(m => m.Username)</td>
            <td>@Html.TextBoxFor(m => m.Username, new { @class = "smallText" })</td>
            <td>@Html.LabelFor(m => m.Password)</td>
            <td>@Html.PasswordFor(m => m.Password, new { @class = "smallText" })</td>
        </tr>
        <tr>
            <td colspan="4" align="right"><input type="submit" value="Login"/></td>
        </tr>
        <tr>
            <td colspan="2">@Html.ValidationSummary()</td>
        </tr>
    </table>

}

Index.cshtml 文件(主内容屏幕)有这个:

    @using GalleryPresentation.Models
@model IndexModel
@{
    ViewBag.Title = "Craig and Melanie's Digital Moments";
}

<br/>
<div style="text-align: center">
    <img src="@Url.Content( Model.RandomImageUrl)" alt="@ViewBag.Title" />
</div>

【问题讨论】:

  • 请包含登录框部分视图cshtml。
  • 看起来我可以使用我的 LoginModel 作为所有其他模型的基类,然后继承它?这似乎可行 - 但这是好的设计/实践吗?我需要确保所有模型都从 LoginModel 继承(我想我会重命名为 BaseModel - 以防需要其他东西?)。
  • 这是一个选项,但我不建议这样做。将 LoginModel 视为基本模型意味着您的每个视图模型都是 LoginModel 的扩展。

标签: asp.net-mvc asp.net-mvc-3 razor


【解决方案1】:

这样的问题并不总是最容易回答的,因为没有直接的解决方案。虽然有几个问题应该考虑。如果可能,我建议您在单独的视图中处理登录验证错误。小登录框的局部视图则不需要强类型视图模型。

没有完美的解决方案,但我认为在每个呈现依赖于 _Layout 的视图的请求上始终创建 LoginModel 对象并没有多大意义。下面的解决方案提倡创建一个单独的登录视图,可用于显式登录尝试和处理任何登录失败。

如果您对此有任何疑问,请随时在评论中提出您的问题,我会尽力回答。

登录框

@using (Html.BeginForm("Index", "Account"))
{
    <table class="smallBox">
        <tr>
            <td>Username</td>
            <td>@Html.TextBox("Username", new { @class = "smallText" })</td>
            <td>Password</td>
            <td>@Html.Password("Password", new { @class = "smallText" })</td>
        </tr>
        <tr>
            <td colspan="4" align="right"><input type="submit" value="Login"/></td>
        </tr>
    </table>
}

账户控制人

public ActionResult Login()
{
    return View();
}

public ActionResult RetryLogin()
{
    ModelState.AddModelError(null, "The Username or Password you entered is invalid.  Please try again.");
    return View("Login");
}

[HttpPost]
public ActionResult Index(LoginModel loginModel)
{
    if(ModelState.IsValid)
    {
        var g = new GallaryImage();
        var user = g.LoginUser(loginModel.Username, loginModel.Password);
        if(user != null) 
        {
            FormsAuthentication.SetAuthCookie(user.username, false);
            return RedirectToAction("Index", "Home");
        }

        ModelState.AddModelError("", "Invalid Username/Password");
    }

    return RedirectToAction("RetryLogin");
}

登录查看

@using (Html.BeginForm("Index", "Account"))
{
    @Html.ValidationSummary()
    <!-- login form here -->
}

【讨论】:

  • 看起来是一个了不起的答案。我不明白 Loginbox 如何适合 _layout - 或者我们是说 Loginbox 不再在 _layout 上,而是一个单独的登录屏幕?
  • 我建议您在 _layout 中使用部分视图和处理 /Account/Login 场景的完整视图。那时的部分观点可能不是真正必要的,但将其分开可能仍然有帮助。
猜你喜欢
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多