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

时间:2010-06-20 21:20:51

标签: 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);
    }

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

如果登录成功,两者都像魅力一样。如果不是,

return View(model)

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

return RedirectToAction("Index", "Home")

显然不起作用。

提示?

5 个答案:

答案 0 :(得分:3)

这当然不是一个新手问题,我已经在网上上下搜索这个问题的答案,到目前为止,我发现的最佳解决方案隐藏在本教程here中。这就是Darin Dimitrov在Ajax刷新时提出的建议。我将总结该链接的重要部分以及为什么不容易修复:/

基于怪异情人的Ajax刷新

使用ajax刷新的解决方案几乎取决于以下函数(奇怪的爱人使用ControllerContext但它不存在,所以我有ControllerExtension):

ControllerExtension.RenderPartialViewToString(this,"mypartial", (object)model)

这个函数是你的模型+模型状态,并将你的局部视图重新呈现为一个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);
};

Jquery解释:

  1. 查找包含我的partial(class =“partial”)的div并在该div中找到该表单
  2. 解除与该表单的任何其他“提交”事件的绑定(我得到了一些奇怪的双提交错误,直到我解除了绑定)。
  3. 使用“live”,以便在替换内容后再次重新绑定
  4. 我们输入功能partialViewUpdate ...
  5. 防止表单完成提交,以便所有内容都可以由ajax处理。
  6. 获取包含我的部分的div(将在稍后使用)
  7. 从表单中获取jquery post url,$(this).attr(“action”)
  8. 获取表单(即我们的模型)并将其序列化为控制器函数,$(this).serialize()
  9. 创建将处理ajax返回值的函数。
  10. 我使用自己的个人json对象,其中StatusCode 1是坏的。所以,如果它不好,那么我拿内容中的内容,这是 RenderPartialViewToString 给我的字符串,我只是替换包含我的部分的div的内容。
  11. 为什么它不能正常“正常工作”

    因此,部分'不仅仅使用模型状态验证的原因是你不能使用POST返回View(模型),因为MVC会将其解析为部分视图的路由地址(login.ascx)部分嵌入的位置(index.aspx)。

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

    这么说吧

    我更喜欢它“只是工作”所以如果有人知道正确/更好的方式做这个pleaaaase分享它!我仍然认为Ajax刷新和ActionFilter解决方案并不是一种干净的方式,因为它几乎使它看起来像部分视图,如果没有某种“技巧”就无法使用表单。

答案 1 :(得分:1)

是的redirecttoaction但是在tempdata中提供了一条错误消息,所以你应该做这样的事情

TempData["errorMsg"] = "incorrect values provided";
return RedirectToAction("Index", "Home")

当然,在主索引中你应该有一个显示消息的div

<%= html.Encode(TempData["errorMsg"]) %>

EDIT 我看到你想维护可能存在问题的模型状态,但你可以做的是在索引操作中传递模型状态或在tempdata中传递modelstate对象。那么你可以做的是检查对象中是否存在模型状态错误,以及是否有检查字段并将错误添加到右侧字段。

答案 2 :(得分:0)

您可以明确指定要返回的视图:

return View("~/Views/Home/Index.aspx", model);

这样可以保留错误信息并呈现正确的视图。

答案 3 :(得分:0)

看看blog上的练习#13。当您使用PRG(Post-Redirect-Get)样式进行编码时,此方法可以很好地传递模型状态信息。您只需创建几个操作过滤器,并将其应用于您的get和post操作。

答案 4 :(得分:0)

使用Ajax.BeginForm时遇到了同样的问题,我需要返回部分视图,但所有的模型状态错误都消失了。 诀窍是将Ajax.BeginForm部分隔离到单独的View,并将RenderPartial包含在另一个包含视图的UpdateTargetId div中。

这样,您可以在拥有模型错误时返回视图模型,或者只显示您选择的一些成功消息(如果有)。 这是一个很好的详细解释: http://xhalent.wordpress.com/2011/02/05/using-unobtrusive-ajax-forms-in-asp-net-mvc3/