tsJensen

A quest for software excellence...

ASP.NET MVC RedirectUrl on Login

In my first attempt at creating a real applicaiton using the new ASP.NET MVC project template (Codeplex Preview 5), I found that when I clicked a new tab I'd created linked to a specific controller and an action I'd decorated with the [Authorize(Roles = "user")] attribute, the "out of the box" Login action did not redirect me to the that controller/action combo once I had successfully logged in.

Here's my solution to the problem. First, I added a hidden value in the Login.aspx form. Second, I added a parameter to the Login action in the Acount controller (AccountController.cs). Let me know if you've found a better way.

Here's the code for the form:

<form method="post" action="<%= Html.AttributeEncode(Url.Action("Login")) %>">
    <div>
        <table>
            <tr>
                <td>
                    Username:
                </td>
                <td>
                    <%= Html.TextBox("username") %>
                </td>
            </tr>
            <tr>
                <td>
                    Password:
                </td>
                <td>
                    <%= Html.Password("password") %>
                </td>
            </tr>
            <tr>
                <td>
                </td>
                <td>
                    <input type="checkbox" name="rememberMe" value="true" />
                    Remember me?
                </td>
            </tr>
            <tr> <!-- Added to handle the returnUrl -->
                <td>
                    <%= Html.Hidden("returnUrl", ViewData["ReturnUrl"].ToString()) %>
                </td>
                <td>
                    <input type="submit" value="Login" />
                </td>
            </tr>
        </table>
    </div>
</form>

Here's the code for the Login action:

public ActionResult Login(string username, string password, bool? rememberMe, string returnUrl)
{
    ViewData["Title"] = "Login";
    string url = (string.IsNullOrEmpty(returnUrl) 
        ? Request.QueryString["ReturnUrl"] ?? string.Empty 
        : returnUrl)
        .Trim('/');
    ViewData["ReturnUrl"] = url;

    // Non-POST requests should just display the Login form 
    if (Request.HttpMethod != "POST")
    {
        return View();
    }

    // Basic parameter validation
    List<string> errors = new List<string>();

    if (String.IsNullOrEmpty(username))
    {
        errors.Add("You must specify a username.");
    }

    if (errors.Count == 0)
    {

        // Attempt to login
        bool loginSuccessful = Provider.ValidateUser(username, password);

        if (loginSuccessful)
        {
            FormsAuth.SetAuthCookie(username, rememberMe ?? false);
            if (url != null && url.Length > 0)
                return RedirectToAction("Index", url);
            else
                return RedirectToAction("Index", "Home");
        }
        else
        {
            errors.Add("The username or password provided is incorrect.");
        }
    }

    // If we got this far, something failed, redisplay form
    ViewData["errors"] = errors;
    ViewData["username"] = username;
    return View();
}