ASP.Net MVC部分视图保持其模型状态?

Spa*_*awk 9 asp.net-mvc partial-views

这可能是一个新手问题.

当我创建ASP.NET MVC2应用程序时,会创建一个带有Action LogIn的帐户控制器,如下所示:

[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
   if (ModelState.IsValid)
   {
      if (MembershipService.ValidateUser(model.UserName, model.Password))
      {
         FormsService.SignIn(model.UserName, model.RememberMe);
         if (!String.IsNullOrEmpty(returnUrl))
         {
            return Redirect(returnUrl);
         }
         else
         {
           return RedirectToAction("Index", "Home");
         }
       }
       else
       {
          ModelState.AddModelError("", "The user name or password provided is incorrect.");
       }
     }

        // If we got this far, something failed, redisplay form
        return View(model);
    }
Run Code Online (Sandbox Code Playgroud)

现在,我不希望有一个登录页面,我希望将登录控件作为更大页面的一部分.所以,我将Login.aspx更改为Login.ascx,并将其集成到我的主视图中,使用Html.RenderPartial或Html.RenderAction.

如果登录成功,两者都像魅力.如果不是,那就是

return View(model)
Run Code Online (Sandbox Code Playgroud)

杀了我 我想要的是回到我的主页面(称之为Home/Index),但是带有局部视图的错误信息.

return RedirectToAction("Index", "Home")
Run Code Online (Sandbox Code Playgroud)

显然不起作用.

提示?

Thi*_*lan 3

这当然不是一个新手问题,我已经在网上搜索了这个问题的答案,到目前为止,我发现的最佳解决方案隐藏在本教程。这就是达林·迪米特洛夫 (Darin Dimitrov) 在阿贾克斯更新中所建议的。我将总结该链接的重要部分以及为什么这不容易修复:/

基于奇怪情人的Ajax刷新

ajax刷新的解决方案很大程度上取决于以下功能(奇怪的爱好者使用ControllerContext,但它对我来说不存在,所以我有ControllerExtension):

ControllerExtension.RenderPartialViewToString(this,"mypartial", (object)model)
Run Code Online (Sandbox Code Playgroud)

该函数采用模型+模型状态并将部分视图重新渲染为 html 字符串。然后,您可以获取该字符串并将其以 json 对象形式发送回某些 javascript 以刷新视图。我用了jquery,它看起来像这样,

$(document).ready(function () {
    var partialViewUpdate = function (e) {
            e.preventDefault(); //no postback
            var partialDiv = $(this).parent(".partial");
            $.post($(this).attr("action"),
                   $(this).serialize(),
                   function (json) {
                   if (json.StatusCode != 0) {
                       // invalid model, return partial 
                       partialDiv.replaceWith(json.Content);
                   }
                   else if (json.Content != null && json.Content != "") {
                       window.location.replace(data.Content);
                   };
           });

    $(".partial").find("form")
                 .unbind('submit')
                 .live("submit", partialViewUpdate);
};
Run Code Online (Sandbox Code Playgroud)

jquery解释:

  1. 查找包含我的部分 (class="partial") 的 div 并找到该 div 中的表单
  2. 使用该表单取消绑定任何其他“提交”事件(在取消绑定之前,我遇到了一些奇怪的双重提交错误)。
  3. 使用“live”,以便一旦内容被替换,它就会再次重新绑定
  4. 一旦我们进入函数partialViewUpdate...
  5. 阻止表单完成提交,以便全部由ajax处理。
  6. 获取包含我的部分内容的 div(稍后将使用它)
  7. 通过从表单 $(this).attr("action") 获取来设置 jquery post url
  8. 采取形式(即我们的模型)并将其序列化为控制器函数 $(this).serialize()
  9. 创建将处理 ajax 返回值的函数。
  10. 我使用我自己的个人 json 对象,其中 StatusCode 1 是错误的。因此,如果情况不好,那么我会采用 Content 中的内容,这是RenderPartialViewToString给我的字符串,我只需替换包含我的部分的 div 的内容。

为什么它不能正常“工作”

因此,部分视图不仅仅适用于模型状态验证的原因是,您无法使用 POST 返回 View(model),因为 MVC 会将其解析为部分视图 (login.ascx) 的路由地址,而不是部分嵌入(index.aspx)。

您也不能使用 RedirectAction(),因为这会将其发送到 (index.aspx) 控制器函数,这相当于清除所有内容并刷新 index.aspx 页面。但是,如果您使用 Chino 和 Thabaza 建议的 ActionFilter,那么当刷新页面并且再次触发 login.ascx 控制器功能时,它将获取该临时数据。然而,如果刷新页面导致客户端代码(例如弹出模式)出现麻烦(即,如果刷新弹出窗口就消失了),则此方法不起作用。

说不是这样

我希望它“刚刚起作用”,所以如果有人知道正确/更好的方法,请分享它!我仍然觉得 Ajax 刷新和 ActionFilter 解决方案不是一种干净的方法,因为它几乎使它看起来像带有表单的部分视图,如果没有某种“技巧”就不可能使用。