ReturnUrl Duplicating Parameters - MVC 4 - asp.net-mvc

I'm having problem with retunUrl what is duplicating my QueryString parameters.
My url is like:
"www.mysite.com/Order/?id=1&item=123"
then, redirect me to login page and the url look like:
"www.mysite.com/login/RedirectUrl=/Order?id=1&item=123&id=1&item=123"
After the user login, the action redirect to:
"www.mysite.com/Order/?id=1&item=123&id=1&item=123"
In my page when i use Request.QueryString["id"] i got an error, because the querystring "ID" is duplicated.
My login Action code look like this:
[HttpPost]
[AllowAnonymous]
public ActionResult Index(LoginModel model, string ReturnUrl)
{
if(VerifyLogin(model))
{
if(ReturnUrl != null)
return Redirect(ReturnUrl);//redirect to url with duplicated parameters
else
return Redirect("/Home");
}
else
{
ModelState.AddModelError("", "Invalid Username or Password");
}
return View();
}
How i can solve this problem?

I think problem is in Order controller or ReturnUrl assignment logic. It might adding url+queryString. If yes you can try something like Request.Url.GetLeftPart(UriPartial.Path) + queryString

Related

RedirectToLocal() goes to a different url

The following code snippet is from my ASP.NET MVC 5 application:
public ActionResult Ask(string id) {
if (!this.User.Identity.IsAuthenticated) {
string retUrl = Request.Url.AbsoluteUri;
return RedirectToAction("Login", "Account", new { returnUrl = retUrl });
}
...
}
The idea is, if the user has not yet logged in, he will be taken to the login page and subsequently be returned back to this "Ask" page.
When the user enters, for example, http://example.com/Home/Ask/12345678, method Ask() gets invoked with the correct value for id. The user is now redirected to the login page.
After Login() code in AccountController successfully authenticates the user, it calls ReturnToLocal(), passing in the url that we expect (http://example.com/Home/Ask/12345678). However, instead of invoking the Ask() method , ASP .NET somehow ends up invoking Index() method.
Appreciate your help in understanding why my redirection is broken. Regards.
Since you did not provide us neither the Login action method nor RedirectToLocal method I am assuming you are using the AccountController from MVC5 template.
If so
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Index", "Home");
}
You can see that RedirectToLocal method checkes if the returnUrl parameter is 'localUrl'.
If not it does invoke Index.
In your Ask method you are passing string retUrl = Request.Url.AbsoluteUri as returnUrl which is not local (starts with http://)!
Try string retUrl = Request.Url.PathAndQuery

How to get requested Url before Login

Some Controller-Actions in my page are decorated with the [Authorize] attribute. The forward to the Login page works perfect, but after successful login, I want to forward to the requested url. With Request.UrlReferrer, I get the url where I come from, but how can I get the requested action (which requires the login)?
The Login() action takes a string parameter called returnUrl which will be used when redirecting from the login.
You can add the returnUrl to the ViewBag and return a view.
For Eg:
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
The target action uses the posted data to authenticate the user and log in the user using FormsAuthentication. It then redirects the user back to the returnUrl.
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (//Validation Check)
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return Redirect(returnUrl); // Redirect to referer
}
ViewBag.ReturnUrl = returnUrl;
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}

back button functionality in MVC application

I have a requirement to implement Back button functionality in MY MVC2 application(with explicit Back buttons in the application, not via browser back button).
I have gone through the link here Back button functionality using ASP.net MVC which advises to use Request.UrlReferrer. and it works well whenever I have a HTTP Get (as it comes up with querystring.) but I face issue when previous page was a HTTP POST with no querystring.
Has anyone worked on a solution like this?
We have initial thoughts of generating and storing links like Stack, and popping out urls one by one when user clicks on 'Back' button. But if there is a better solution\design pattern which helps me achieve that?
You could store the returnurl to actionresult routevalues and have a html helper for back link.
Helper:
public static class HtmlHelpersExtensions
{
public static MvcHtmlString BackLink(this HtmlHelper helper,string defaultAction)
{
string returnUrl = HttpContext.Current.Request["returnUrl"];
// If there's return url param redirect to there
if (!String.IsNullOrEmpty(returnUrl))
{
return new MvcHtmlString("<a href=" + returnUrl + " >Back</a>");
}
// if user just posted and there's no returnurl, redirect us to default
else if (HttpContext.Current.Request.HttpMethod == "POST")
{
return helper.ActionLink("Back", defaultAction);
}
// we didn't post anything so we can safely go back to previous url
return new MvcHtmlString("<a href=" + HttpContext.Current.Request.UrlReferrer.ToString() + " >Back</a>");
}
}
Controller:
public ActionResult MyAction(string returnUrl)
{
return View(new MyModel());
}
[HttpPost]
public ActionResult MyAction(MyModel mm, string returnUrl)
{
if (ModelState.IsValid)
{
// No returnurl, redirect us to somewhere
if (string.IsNullOrEmpty(returnUrl))
return RedirectToAction("Index");
// redirect back
return Redirect(returnUrl);
}
return View(mm);
}
Usage:
#Html.ActionLink("MyAction", "MyAction", new { returnUrl = Request.RawUrl.ToString() })
Backlink in MyAction.cshtml
#Html.BackLink("Index")
Now the helper decides whether it uses returnUrl param, default action or takes you back via urlreferrer.

ASP.NET MVC 3 FormsAuthentication ReturnURL

I am using Forms Authentication in my MVC 3 app and having a problem with my return URL.
When I mark an action <Authorize> on the Home controller, it redirects to the login page and works, but the return URL is then /, so when it redirects, it is redirecting to the root of the the current URL Authorize.
So the URL's are like this:
http://localhost/ - Controller = Home - Action = Index
http://localhost/Authentication/LogOn
I end up with this: http://localhost/Authentication/LogOn?ReturnURL=~%2F, I need to get back to http://localhost/
Help!! :)
Try changing your Account controllers LogOn action to something like this:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
http://localhost/Authentication/LogOn?ReturnURL=~%2F,
it means home url is duplicated

Default MVC web app has no ReturnUrl

When implementing an MVC web app with FormsAuthentication, it would appear that the FormsAuthentication mechanism automagically appends ?ReturnUrl=/ to your mvc routes. I did notice, though, that the default web application which MVC 3 provides out of the box implements FormsAuthentication but does not appear to suffer from the appended ReturnUrl=/ problem. I've looked through the code and can't see where this is being handled. Anyone know?
In the LogOn action of the AccountController, you'll see that if a return url is present, the user will be redirected to it after a successful log on:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Try adding the [Authorize] attribute to the Action or controller. This will generate the url needed to redirect after login.

Resources