Reputation: 8293
I have a login widget that is a partial view that I want updated with model validation errors when there is a problem otherwise the page should be reloaded.
I have the following
LogOn.cshtml
@{
var ajaxOpts = new AjaxOptions {OnSuccess = "success"};
}
<div id="login">
@Html.ValidationSummary(excludePropertyErrors: true)
<h2>Start by Logging in</h2>
@using (Ajax.BeginForm("LogOn", "Account", ajaxOpts))
{
@Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<table width="100%" border="0" cellspacing="0" cellpadding="5">
<tr>
<td>
<span class="bluey">Username:</span><br />
@Html.TextBoxFor(m => m.UserName, new {tabindex = "1", Class = "field"})
@Html.ValidationMessageFor(m => m.UserName, "*")
</td>
<td>
<span class="bluey">Password:</span><br />
@Html.TextBoxFor(m => m.Password, new {tabindex = "2", Class = "field"})
@Html.ValidationMessageFor(m => m.Password, "*")
</td>
</tr>
<tr>
<td>
<input name="login" type="submit" value="Submit" class="input_btn" tabindex="3" />
</td>
<td>@Html.CheckBoxFor(m => m.RememberMe) @Html.LabelFor(m => m.RememberMe) <span class="bluey"> | </span> @Html.ActionLink("Forgot Password?", "Password", "User")</td>
</tr>
</table>
}
</div>
<script>
function success(context) {
//var returnUrl = context.get_data().returnUrl;
//if (returnUrl) {
// window.location.href = returnUrl;
//} else {
$("#login").replaceWith(context);
//}
}
</script>
and the action that gets called is
[HttpPost]
public ActionResult LogOn(LogOnModel userDetails, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(userDetails.UserName, userDetails.Password))
{
FormsAuthentication.SetAuthCookie(userDetails.UserName, userDetails.RememberMe);
return Redirect(returnUrl);
}
ModelState.AddModelError("", "The username or password provided was incorrect");
}
return PartialView(userDetails);
}
I have it working so that when data is incorrect the partial view is redisplayed with errors however this part only works if I comment out the other lines of javascript in success(context) that are there for when the user logs in successfully and the page should be redirected.
Is there a better way to do this?
I did try returning anonymous objects with Json() that had a status property and either a returnUrl or Html however I could not figure out how to get the html that would have been generated by PartialView(userDetails) into the Json() call, and it seems like that might be the wrong way to go about things anyway.
Upvotes: 2
Views: 2915
Reputation: 1038720
You cannot redirect in an AJAX call. You could return a JSON object from the server pointing to the url to redirect to and then perform the actual redirect in your success callback.
function success(result) {
if (result.returnUrl) {
// the controller action returned JSON
window.location.href = returnUrl;
} else {
// the controller action returned a partial
$('#login').html(result);
}
}
Now in your controller action in case of success simply return the return url instead of redirecting:
return Json(new { returnUrl = returnUrl });
By the way you already seem to have the return url in the view: Request.Url.PathAndQuery
. I don't see the point of having it transit to the server and back. You could simply return some JSON boolean indicating the success and perform the redirect in the success callback to the url.
Upvotes: 2