标题可能不那么清楚(因为我找不到更好的标题)但我想弄清楚的是当你有一个正常(而不是部分)视图时,通常会有一个简单呈现的GET动作方法具有视图模型的新实例的视图,以及接受视图模型的实例作为参数的POST操作方法(通常具有相同名称).在POST操作方法内部,检查ModelState是否有效,您是否执行了您应该执行的操作,如果不是,则使用相同的视图模型实例再次呈现视图以显示任何错误.
这实际上是我对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
}
}
更新:这是登录视图:
@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>
那我该怎么做呢?有什么建议?
更新:(在Darin回答之后)
以下是我的Login操作方法现在的样子:
[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);
}
}
最佳答案 正如您在评论部分所述,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();
}
}
});
}