I use a combination of the above suggestion and Request.UrlReferrer to get the previous location:
public ActionResult LogOn(string returnUrl)
{
//So that the user can be referred back to where they were when they click logon
if (string.IsNullOrEmpty(returnUrl) && Request.UrlReferrer != null)
returnUrl = Server.UrlEncode(Request.UrlReferrer.PathAndQuery);
if (Url.IsLocalUrl(returnUrl) && !string.IsNullOrEmpty(returnUrl))
{
ViewBag.ReturnURL = returnUrl;
}
return View();
}
This way I don't have to put the location in the ActionLink.
I populate a hidden field in the login page using the ViewBag.ReturnURL. Then in the Login HTTPPost ActionResult I redirect the user to the location in the hidden field (if there is one):
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
//returnURL needs to be decoded
string decodedUrl = "";
if (!string.IsNullOrEmpty(returnUrl))
decodedUrl = Server.UrlDecode(returnUrl);
//Login logic...
if (Url.IsLocalUrl(decodedUrl))
{
return Redirect(decodedUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
//Utilities
public static ReturnUrl GetReturnUrlValues(string returnUrl)
{
//0:Action,1:Controller,2:Area:,3:Id
ReturnUrl vm = new ReturnUrl();
using (TBBSEntities context = new TBBSEntities())
{
if (returnUrl != null && returnUrl.Length > 10)
{
var counterValue = returnUrl.Split('/');
vm.Action = counterValue[0];
vm.Controller = counterValue[1];
vm.Area = counterValue[2] == "0" ? "" : counterValue[2] ;
vm.Id = Convert.ToInt32(counterValue[3]);
vm.NullStatus = true;
return vm;
}
vm.NullStatus = false;
return vm;
}
}
//Controller
var transformUrl = Utilities.GetReturnUrlValues(returnUrl);
if (transformUrl.NullStatus)
{
return RedirectToAction(transformUrl.Action, transformUrl.Controller,
new { area = transformUrl.Area, id = transformUrl.Id });
}
return RedirectToAction("Action", "Controller", new { area = "Area", Id});
//View
var returnUrl = "Action/Controller/Area/" + @Model.Id;
In this case you could have your LogOn action take a returnUrl parameter and if it is not empty, instead of redirecting to Home/Index you could return Redirect(returnUrl);. Take a look at the default AccountController generated by VS when you create a new project. It does exactly that.
If the ReturnURL is null, make sure you are calling the action method from the view as follows:
// FormMethod.post is optional
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
// login view html
}
Account controller:
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}