如何使用MVC使用多个表单显示ValidationSummary

Ric*_*ddy 5 validation asp.net-mvc-3

我已经查看了本网站和其他网站上提供的许多解决方案来解决我的问题,但似乎没有一个适合我的解决方案。

在我的布局页面上,我在屏幕顶部有一个登录区域。除非用户登录,否则它始终存在。此登录表单上有一个 ValidationSummary 并且每次我使用站点上的另一个表单回发时,都会触发此登录表单的验证。

我几乎可以肯定这取决于我如何从我的布局页面调用这个登录页面。它不是共享文件夹中的局部视图,它位于我项目的一个区域中。在我的布局页面上,我像这样调用登录表单:

@Html.Action("LogOn", "Account", new { area = "Store" })
Run Code Online (Sandbox Code Playgroud)

登录页面包含以下内容:

@model Project.ViewModels.LogOn_ViewModel

@{
    Layout = null;
}

@using (Ajax.BeginForm("LogOn", "Account", new { @area = "Store" }, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "LoginContainer", LoadingElementId = "actionLoaderImage" }, new { id="LogonForm" }))
{
    @Html.AntiForgeryToken()

    <div class="loginArea">
        <div class="notRegistered">
            <h4>Not registered yet?</h4>
            Register now<br/>
            @Html.ActionLink("Register", "Index", "SignUp", new { area = "Store" }, new { @class = "greenButton" })
        </div> <!-- /notRegistered -->

        <div class="loginForm">
            <div class="formFields">
                <label class="inline">@Html.LabelFor(m => m.UserName)</label>
                @Html.TextBoxFor(m => m.UserName)
                <label class="inline">@Html.LabelFor(m => m.Password)</label>
                @Html.PasswordFor(m => m.Password)
                <input type="submit" name="LogIn" value="Log in" class="blueButton" />
                <img id="actionLoaderImage" src="@Url.Content("~/Content/web/images/loader.gif")" alt="icon" style="margin-right:15px; display:none;" /> 
                @Html.ValidationSummary()
            </div>
        </div> <!-- /loginForm -->
    </div> <!-- /loginArea -->
}
Run Code Online (Sandbox Code Playgroud)

登录控制器是标准的东西:

        // GET: /Account/Logon

        public ActionResult LogOn()
        {
            // if logged in show logged in view
            if (User.Identity.IsAuthenticated)
                return View("LoggedIn");

            return View();
        }


        // POST: /Account/Logon

        [HttpPost]
        public ActionResult LogOn(LogOn_ViewModel model)
        {
            if (ModelState.IsValid)
            {
                if (SecurityService.Login(model.UserName, model.Password, model.RememberMe))
                {
                    return View("LoggedIn");
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }
            return PartialView(model);
        }
Run Code Online (Sandbox Code Playgroud)

我怀疑这里发生的事情是 Html.Action 正在“发布”登录表单,如果帖子发生在页面上的其他地方。这是有道理的,因为布局页面本身将作为表单发布操作的一部分发布。

我尝试从其他一些 SO 问题和博客(http://blogs.imeta.co.uk/MBest/archive/2010/01/19/833.aspx)中实现自定义验证器示例,但我发现使用这些示例不会显示带有客户端验证的验证摘要,这对我来说没什么用。

我正在寻找的解决方案需要允许客户端和服务器端验证都出现在正确的表单中。有没有人有这样的例子使用MVC?如果可能的话,我想避免使用 jquery 手动处理客户端验证,而只是使用框架来为我处理工作。

感谢您的建议,丰富

Ric*_*ddy 2

在研究这个问题的时间比我愿意承认的时间长之后,一旦你知道怎么做,答案就一如既往地简单!

对于其他遇到此问题的人来说,解决此问题的方法是重命名您的操作,以便您的 POST 操作的名称与 GET 操作的名称不同。这样,当 Layout 页面回发并触发 PartialView 也回发时,您的 PartialView 仅有 GET 操作,因此不会触发 ValidationSummary。

根据上面的示例,我更改了表单以回发到我的登录部分视图的另一个操作,这为我解决了这个问题。

在我的布局页面中,商店区域中部分内容的链接保持不变:

@Html.Action("LogOn", "Account", new { area = "Store" })
Run Code Online (Sandbox Code Playgroud)

然后,登录表单操作被更改为指向一个新操作 - 不与 GET 操作同名:

    @using (Ajax.BeginForm("ConfirmLogon", "Account", new { @area = "Store" }, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "LoginContainer", LoadingElementId = "actionLoaderImage" }, new { id="LogonForm" }))
    { 
      .... 
    }
Run Code Online (Sandbox Code Playgroud)

然后,我刚刚重命名了我的控制器操作,以便它对 POST 操作具有不同的操作名称,这样当使用帖子调用布局页面并且使用 POST 操作加载部分时,它不会调用我的登录 POST 操作:

        // POST: /Account/ConfirmLogon

        [HttpPost]
        public ActionResult ConfirmLogon(LogOn_ViewModel model)
        {
            if (ModelState.IsValid)
            {
                if (SecurityService.Login(model.UserName, model.Password, model.RememberMe))
                {
                    return PartialView("LoggedIn");
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }
            return PartialView("Logon",model);
        }
Run Code Online (Sandbox Code Playgroud)

希望这能帮助其他人解决这个问题。现在看起来很明显,但让我发疯:D