ASP.NET MVC Login ReturnUrl always NULL?

asp.net MvcRedirectLogin

asp.net Mvc Problem Overview


Using Forms Authentication in ASP.NET MVC when trying to log back into a site, it puts a ReturnUrl parameter in the query string. My Logon action method accepts a "returnUrl" string. However it seems that returnUrl string is always null, even when it is clearly in the query string. Any thoughts on why this might be the case or a possible fix?

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

This tends to happen when you're using one generic logon form, but you're explicitly specifying the Controller and ActionMethod (which is causing a form post, but losing the querystring)

Just to clarify, this is what your code should look like in your BeginForm:

Html.BeginForm("LogOn", "Account", new { ReturnUrl = Request.QueryString["ReturnUrl"] })

> EDIT: This is by design as RickAnd mentions in comments below. However it doesn't allow for the UI pattern of being deep in a site, clicking on LogOn, then returning to the page you were previously on, if it allows anonymous users. It's a commonly requested pattern. David Allen's approach to LogOff would also work nicely for a clean redirect at LogOn.

Solution 2 - asp.net Mvc

Maybe you don't include the ReturnURL parameter into you login form's action attribute, thus posting to a URL without that parameter?

Solution 3 - asp.net Mvc

Basically, The Asp.net MVC has some hidden features. For Example when you pass variable 'id' to controller action, it interprets 'id' as default identifier and puts it on browser query with fore slash.By using another name instead of 'id' we will see '?' rather than fore slash. Because of setting the 'id' name on RegisterRoutes method on global.asax file.

In this Problem you have created a custom data passer to controller by using this code:

using(Html.BeginForm("LogOn", "Account", FormMethod.Post))
{
//form fields
}

So Asp.net MVC ignores other useful data to pass to controller action, and we'll see returnUrl always null.

While, by using this, Asp.net MVC acts Correctly and returnUrl is mounted:

using(Html.BeginForm())
{
//form fields in LogOn View
}

By the way, When we use custom data passer to controller action, must pass another data manually like this:

using(Html.BeginForm("LogOn", "Account", new {ReturnUrl = Request.QueryString["ReturnUrl"] }))
{
//form fields
}

Solution 4 - asp.net Mvc

There are two ways I can think of to deal with logon and logoff scenarios. Dave Beer outlined one way, above. There is another approach that works in many situations. I used it when I coded the NerdDinner tutorial. The tutorial provides us with a logoff function that logs you off and takes you home. I did not want that. I wanted to return to the page I was on before I logged off. So I modified my Account controller logoff action to look like this

   public ActionResult LogOff()
    {
        FormsService.SignOut();
        return Redirect(Request.UrlReferrer.ToString());
    }

You can get fancier and pass in a returnUrl and test for it, in case you want to override this behavior. But I don't need that. This achieves the desired result. The Logon can work similarly. Maybe there are ways to use the MVC framework to do this for me, but until I learn them, this is VERY simple and works reliably.

Solution 5 - asp.net Mvc

Try the following:

        public static MvcForm BeginForm(this HtmlHelper htmlHelper, string id)
    {
        string formAction = htmlHelper.ViewContext.HttpContext.Request.RawUrl;

        TagBuilder tagBuilder = new TagBuilder("form");

        tagBuilder.MergeAttribute("id", id);
        tagBuilder.MergeAttribute("action", formAction);
        tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(FormMethod.Post), true);

        HttpResponseBase httpResponse = htmlHelper.ViewContext.HttpContext.Response;
        httpResponse.Write(tagBuilder.ToString(TagRenderMode.StartTag));

        return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
    }

First ensure you have set the login url in the web.config, Next, ensure your Signin Form does not contain anything like action, for example:

View:

<%using (Html.BeginForm()){%> <%}%>

If you specify action you will always get null for return url:

Controller:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SignIn(string userName, string password, bool? rememberMe, string returnUrl)
{
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaherrickView Question on Stackoverflow
Solution 1 - asp.net MvcdavewasthereView Answer on Stackoverflow
Solution 2 - asp.net MvcÇağdaş TekinView Answer on Stackoverflow
Solution 3 - asp.net MvcAmirhossein MehrvarziView Answer on Stackoverflow
Solution 4 - asp.net MvcDavid AllenView Answer on Stackoverflow
Solution 5 - asp.net MvcKazi Manzur RashidView Answer on Stackoverflow