Common mistake or misunderstanding why login action doesn’t have ReturnUrl value, even if there is string parameter with value in the page URL. If you think about it more, you will get it – ReturnUrl  is in the page URL but not in the action URL of the login form. The trick is to pass this parameter to the form inputs or action URL parameters be submitted with login form request. It’s very easy to do with MVC.

First, in the view pass parameter to the form by specifying rote parameter for form action:

@model LogOnModel
@{
	ViewBag.Title = "Login | kitsula.com";
	Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>LogOn</h1>
<img src="/Content/Img/login.png" alt="Login" id="imgLogin" />
@using (Html.BeginForm("LogOn", "Account", new { ReturnUrl = Request.QueryString["ReturnUrl"]}, FormMethod.Post, new { @id = "formLogOn"})) { 
	@Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.")
	<div>
		<fieldset>
			<legend></legend>
			<div class="editor-label">
			    @Html.LabelFor(m => m.UserName)
			</div>
			<div class="editor-field">
			    @Html.TextBoxFor(m => m.UserName)
			    @Html.ValidationMessageFor(m => m.UserName)
			</div>
			<br class="clearer" />
			<div class="editor-label">
			    @Html.LabelFor(m => m.Password)
			</div>
			<div class="editor-field">
			    @Html.PasswordFor(m => m.Password)
			    @Html.ValidationMessageFor(m => m.Password)
			</div>
			<br class="clearer" />
			<div class="editor-label"> </div>
			<div class="editor-field">
			    @Html.CheckBoxFor(m => m.RememberMe)
			    @Html.LabelFor(m => m.RememberMe)
			</div>
			<br class="clearer" />
			@Html.HiddenFor(m => m.ReturnUrl)
			<div class="editor-label"> </div>
			<div class="editor-field">
			    <input type="submit" value="Log On"/>
			</div>
		</fieldset>
	</div>
}

ReturnUrl parameter will be passed to the server with form submit request. Now we should handle it on the server. You can declare on action handler separate ReturnUrl parameter or it can be a part of the login model:

public class LogOnModel {

	[Required]
	[StringLength(30)]
	[DisplayName("Username")]
	public string UserName { get; set; }

	[Required]
	[StringLength(50)]
	[DataType(DataType.Password)]
	[DisplayName("Password")]
	public string Password { get; set; }

	[DisplayName("Remember me?")]
	public bool RememberMe { get; set; }

	public string ReturnUrl { get; set; }
}

And action itself:

//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model) {

	if (ModelState.IsValid) {
		if (new KitsulaMembershipProvider().ValidateUser(model.UserName, model.Password)) {
			FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
			if (!string.IsNullOrEmpty(model.ReturnUrl))
				return Redirect(model.ReturnUrl);
			return RedirectToAction("Index", "Home");
		}
		ModelState.AddModelError("Password", "The user name or password provided is incorrect.");
	}
 
	// If we got this far, something failed, redisplay form
	return View(model);
}

On successful login just check if ReturnUrl is not empty and redirect to the URL or default action.

Comments

Luis
18 November 2014 | 09:59 -05:00

Thank you very much!! This was exactly what I needed! You rock! : )

Satish
19 January 2016 | 11:03 +05:30

if we need to another window like failure message so hoew to achieve it.

Join the discussion

Captcha