4

标题可能不是很清楚(因为我找不到更好的),但我试图找出的是当你有一个正常(而不是部分)的看法,通常有一个GET操作方法,该方法仅使用视图模型的新实例呈现视图,并使用POST操作方法(通常具有相同名称)接受视图模型的实例作为参数。在POST动作方法中,您检查ModelState是否有效,如果不是,则使用相同视图模型实例再次渲染视图以显示任何错误。PartialViews和验证(回发)

这实际上是我真正喜欢关于ASP.NET MVC的东西之一,但是这对于部分视图是如何工作的?如果我使用视图模型的实例渲染部分视图,则它仅在整个Web应用程序的上下文之外显示具有白色背景的部分视图。如果我回发传递视图模型实例的普通视图,则会导致StackOverflowException。

下面是一个例子:

public ActionResult Login() 
    { 
     return PartialView(new LoginViewModel()); 
    } 

    [HttpPost] 
    public ActionResult Login(LoginViewModel dto) 
    { 
     bool flag = false; 
     if (ModelState.IsValid) 
     { 
      if (_userService.AuthenticateUser(dto.Email, dto.Password, false)) { 
       var user = _userService.GetUserByEmail(dto.Email); 
       var uSession = new UserSession 
       { 
        ID = user.Id, 
        Nickname = user.Nickname 
       }; 
       SessionManager.RegisterSession(SessionKeys.User, uSession); 
       flag = true; 

       if(dto.RememberMe) 
       { 
        _appCookies.Email = dto.Email; 
        _appCookies.Password = dto.Password; 
       } 
      } 
     } 
     if (flag) 
      return RedirectToAction("Index", "Home"); 
     else 
     { 
      ViewData.Add("InvalidLogin", "The login info you provided were incorrect."); 
      return View(dto); //causes a StackOverflowException 
     } 
    } 

UPDATE:这里的登录视图:

所以
@inherits ModelWebViewPage<Sharwe.MVC.ViewModels.LoginViewModel> 

<div class="userFormHeader"><h2>Login</h2></div> 
<div id="loginBox"> 
    @using(Html.BeginForm("Login", "User", FormMethod.Post)) 
    { 
     @Html.ValidationSummary(true) 

     <div id="loginFormFields"> 
      <div class="display-field">@this.TextBox(m => m.Email).Class("emailField").Attr("rel", "email").Class("autoText")</div> 

      <div class="display-field">@this.TextBox(m => m.Password).Class("passwordField").Attr("rel", "password").Class("autoText")</div> 

      <div>@this.CheckBox(m => m.RememberMe) <span class="smallText">remember me</span></div> 
     </div> 

     <div id="loginFormActions"> 
      <div><input type="submit" id="loginSubmit" class="okButton" name="loginSubmit" value="Ok" /></div> 
      <div> @this.Html.ActionLink("forgot password", "ForgotPassword", "User", new { @class = "verySmallText" })</div> 
     </div> 
    } 
</div> 

应该怎么做呢?有什么建议么?

UPDATE:(Darin的答案后)

这里是我的登陆行动方法现在的样子:

[HttpPost] 
    public ActionResult Login(LoginViewModel dto) 
    { 
     bool flag = false; 
     if (ModelState.IsValid) 
     { 
      if (_userService.AuthenticateUser(dto.Email, dto.Password, false)) 
      { 
       var user = _userService.GetUserByEmail(dto.Email); 
       var uSession = new UserSession 
       { 
        ID = user.Id, 
        Nickname = user.Nickname 
       }; 
       SessionManager.RegisterSession(SessionKeys.User, uSession); 
       flag = true; 

       if (dto.RememberMe) 
       { 
        //create the authentication ticket 
        var authTicket = new FormsAuthenticationTicket(
         1, 
         user.Id.ToString(), //user id 
         DateTime.Now, 
         DateTime.Now.AddMinutes(20), // expiry 
         true, //true to remember 
         "", //roles 
         "/" 
         ); 

        //encrypt the ticket and add it to a cookie 
        var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, 
               FormsAuthentication.Encrypt(authTicket)); 
        Response.Cookies.Add(cookie); 
       } 
      } 
     } 
     if (flag) 
     { 
      return Json(new { redirectTo = Url.Action("Index", "Home") }); 
     } 
     else 
     { 
      ViewData.Add("InvalidLogin", "The login info you provided were incorrect."); 
      return PartialView(dto); 
     } 
    } 
+0

显示我们登录查看 – archil 2011-04-11 10:50:30

+0

@archil代码:我已经更新我的职务。 – Kassem 2011-04-11 10:54:45

+2

AJAX是您的选择吗? – 2011-04-11 11:08:53

回答

2

当您在留言节AJAX是一个选择说明以下是如何通过AJAX化登录表单来继续操作。 jquery form plugin非常适合这份工作,我会强烈推荐它。

所以,你可以提供一个ID在登录查看登录表单:

@inherits ModelWebViewPage<Sharwe.MVC.ViewModels.LoginViewModel> 
<div class="userFormHeader"><h2>Login</h2></div> 
<div id="loginBox"> 
    @using(Html.BeginForm("Login", "User", null, FormMethod.Post, new { id = "loginForm" })) 
    { 
     ... 
    } 
</div> 

,然后包括一个JavaScript将AJAxify这种形式:

$(function() { 
    ajaxifyLoginForm(); 
}); 

function ajaxifyLoginForm() { 
    $('#loginForm').ajaxForm({ 
     success: function(html) { 
      $('#loginBox').html(html); 
      ajaxifyLoginForm(); 
     } 
    }); 
} 

现在所有剩下的就是在出现错误的情况下返回Login控制器动作的部分视图:

return PartialView(dto); 

我们也需要处理成功案例。这可以通过返回一个JSON字符串来完成:

return Json(new { redirectTo = Url.Action("Index", "Home") }); 

,然后适应客户端脚本:

function ajaxifyLoginForm() { 
    $('#loginForm').ajaxForm({ 
     success: function(data) { 
      if (data.redirectTo != null && data.redirectTo != '') { 
       // Everything went fine => the user is successfully 
       // authenticated let's redirect him 
       window.location.href = data.redirectTo; 
      } else { 
       // the model state was invalid or the user entered incorrect 
       // credentials => refresh the login partial in the DOM and 
       // reajaxify the form: 
       $('#loginBox').html(data); 
       ajaxifyLoginForm(); 
      } 
     } 
    }); 
} 
+0

@Darin Dimitrov:不幸的是,这并没有奏效。出于某种原因,无论登录是否有效,它都会在登录表单中加载网站的副本!我编辑了我的帖子,看到我更新的登录操作方法,并让我知道如果我搞砸了什么... – Kassem 2011-04-11 12:37:38

+0

@Darin Dimitrov:我想通过登录总是失败,因为我需要将类型设置为'POST'。但是,我用萤火虫检查发布的数据,显然没有发布任何内容!我是否需要序列化文本框的值或什么? – Kassem 2011-04-11 14:10:30

+0

@Kassem,不,你不需要序列化它们。这就是jQuery表单插件自动执行的操作。 – 2011-04-11 14:15:35