views:

68

answers:

3

Let's take as an example a standard default ASP.NET MVC project created by Visual Studio.

Being on ../Home/About page I click Log On link and get to the ../Account/LogOn page. After logging in I'm being redirected to the Home page, not to the Home/About page from which I get to the LogOn page. Why is that?

Though, in the AccountController we have:

[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 (!String.IsNullOrEmpty(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);
    }

Is the problem in the fact that string returnUrl is empty after clicking Log On link? How to assign it a value when clicking the Log on link?

How to redirect a user, after logging in, to the page, from which he/she came from?

View code:

<asp:Content ID="loginContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>Log On</h2>
<p>
    Please enter your username and password. <%: Html.ActionLink("Register", "Register") %> if you don't have an account.
</p>

<% using (Html.BeginForm()) { %>
    <%: Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") %>
    <div>
        <fieldset>
            <legend>Account Information</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>

            <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>

            <div class="editor-label">
                <%: Html.CheckBoxFor(m => m.RememberMe) %>
                <%: Html.LabelFor(m => m.RememberMe) %>
            </div>

            <p>
                <input type="submit" value="Log On" />
            </p>
        </fieldset>
    </div>
<% } %>

Edited (added):

It appeared that above view code is not very relevant to the problem, instead I should have looked at this (LogOnUserControl.ascx):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
    if (Request.IsAuthenticated) {
%>
    Welcome <b><%: Page.User.Identity.Name %></b>!
    [ <%: Html.ActionLink("Log Off", "LogOff", "Account") %> ]
<%
}
else {
%> 
    [ <%: Html.ActionLink("Log On", "LogOn", "Account")%> ]
<%
}
%>
+1  A: 

Why this is is pretty easy to answer.

The ReturnURL is not set, because you go to logOn by yourself by clicking on Log On

If a page has restrictions to either roles or users, youll get automatically redirected to the logOn action, and the ReturnUrl will be set.

http://localhost:50152/Account/LogOn?ReturnUrl=%2f2011-2012%2fReeksen

what one could do is change the Log On button in the corner to take a ReturnURL with it.

Stefanvds
Thanks for the useful info, +1
rem
+2  A: 

When you generate the LogOn link you need to pass the returnUrl query string parameter:

<%: Html.ActionLink("Log On", "LogOn", "Account", new { returnUrl = Request.Url }, null)%>
Darin Dimitrov
Yes, this way it perfectly works. Thanks. +1
rem
+1  A: 

You are submitting a form, and your form doesn't have a value for the returnurl, so I am not surprised that your returnurl is null.

Here's what you need to do at the client end.

-- Add this within your form somewhere

<input type='hidden' value=<%myurl%> name='returnurl' />

Then you're using model binding... I don't use model binding, so I am not sure whether returnurl will be bound correctly to the extra parameter you've declared in addition to the model.

If not then do this within your server side code

myurl = Request.Form["returnurl"] 

Should work for you now.

Cyril Gupta
Cyril, I went another way in solving this. Anyway, thanks for your proposal. It will help me to better understand the issue. +1
rem