How To Create a Log-in Page With Umbraco 7

Allowing your site visitor to fill in forms and post information to your website is a key aspect of many websites.  Today’s tutorial is the first in a several part guide about how to implement forms within your project. In today’s guide, we’re going to cover a simple log-in form and all the code you will need to implement it.

Surface Controller

When you build a bog standard MVC website, you should be well aware of the MVC page controller.  In Umbraco when we deal with forms and postbacks, we need some extra functionality to integrate our forms with Umbraco and luckily, Umbraco has provided this functionality with a handy base controller called the surface controller. The surface controller is like a normal page controller, however, it has a few thrown in Umbraco based benefits, for example, a surface controller knows things like the current Umbraco page for the request.  Basically.. when you think about implementing a form in your website, you will need a surface controller to deal with the response.  Without a surface controller, none of this would be possible.  A surface controller is a bit more powerful than a normal MVC controller as it knows a lot more about Umbraco,

The View Model

Like any good architected MVC website, we will need a basic view model to pass the data from the form to the controller. This will look like this:

public class LoginViewModel
{
public string Login { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
}

The Controller

The next part is creating a controller to deal with the log-in logic and return the correct views, which will look like this:

public class MembershipController : Umbraco.Web.Mvc.SurfaceController
{
[HttpGet]
[ActionName("MemberLogin")]
public ActionResult Index()
{
return PartialView("LoginForm", new LoginViewModel());
}
[HttpGet]
public ActionResult Logout()
{
Session.Clear();
FormsAuthentication.SignOut();
return Redirect("/");
}
[HttpPost]
[ActionName("MemberLogin")]
public ActionResult Validate(LoginViewModel model)
{
if (Membership.ValidateUser(model.Login, model.Password))
{
FormsAuthentication.SetAuthCookie(model.Login, model.RememberMe);
return RedirectToCurrentUmbracoPage();
}
TempData["Status"] = "Invalid Log-in Credentials";
return RedirectToCurrentUmbracoPage();
}
}

We inherit from the surface controller and implement three actions, a standard Index action that will render the log-in view, a log-out action (does what it says on the can) and a validate action. The validate action will be used to try and log the user into the website, if the credentials are successful the user will be re-directed to the homepage with a welcome message, if the credentials are invalid they will see an error message.

Note the ActionName attributes above Index and Validate. Without these, you will see the following error.

Could not find a Surface controller route in the RouteTable for controller name MembershipController

This is because the surface controller is expecting certain actions to be named appropriately, so follow the syntax.

The Partial View

In my partials folder, I added a view called LoginForm.cshtml, which looks like this:

@using JondJonesSampleSite.Controllers;
@model JonDJones.BusinessLayer.ViewModel.LoginViewModel
@if (User.Identity.IsAuthenticated)
{
<p>
Welcome, @User.Identity.Name
</p>
<p>
@Html.ActionLink("Log out", "Logout", "Membership")
</p>
}
else
{
using (Html.BeginUmbracoForm<MembershipController>("MemberLogin"))
{
@Html.EditorFor(x => Model)
<input type="submit" />
}
<p>@TempData["Status"]</p>
}   

The view uses the view model as the main model. In the top half of the page, we use the IsAuthenticated to determine which snippet of HTML to display to the user.  If the user is logged in, they will see an output button that, when clicked, will call the logout action in the surface controller.

If they are not logged in, they will see an input form based off of the view model, that will post the form data on submissions to the MemberLogin method in the controller.

The last bit of the file is used to display any error messages to the user.  Another way of doing this is by adding an error message property to the view model.

Adding The Partial

The last bit is to add a reference to the partial view from your page template; this is done using the Action helper, like so:

@Html.Action("MemberLogin", "Membership");

Code Sample

You can download a working copy of this example from my Github account here:

https://github.com/jondjones/JondJones.com.Umbraco.Forms

Conclusion

There we have it; if you implement the code above you should now have a simple web form that will log a user into your Umbraco website. In order to do this, we have to use the inbuilt Umbraco controller, called the surface controller.

We implemented a view model and three actions, a first-page load action (the index), a logout action and a validate action.

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

More Posts

9 replies
  1. Glynn
    Glynn says:

    This looks so simple and exactly what I need … but

    I get this error on logout

    @Html.ActionLink(“Log out”, “Logout”, “Membership”, new { @class = “header-sign-out” })

    There is not current PublishedContentRequest, it must be initialized before the RenderRouteHandler executes

    Any ideas ?

    Many thanks in advance
    Glynn

    Reply
  2. Colin
    Colin says:

    Thanks for this article. However, I am running into an error that I’m having trouble overcoming…

    “Cannot redirect from a Child Action”

    It seems that when the child action returns ‘RedirectToCurrentUmbracoPage()”, this error occurs. I’ve never run into this before. Have you ever seen this?

    Thanks!

    Reply
    • Jon D Jones
      Jon D Jones says:

      I’ve run into this one a few times. It’s usually down to having you action in the wrong place, how have you architected your page? I’m guessing you will probably need to move the action, into a higher controller, like your base controller. I’d be interested to hear

      Reply
  3. B Taber
    B Taber says:

    Very instructive project, thank you.

    After creating an Umbraco account in SQL I’m able to login to the backoffice, but the site’s homepage login always returns “Invalid Log-in Credentials” for those same credentials.

    Membership.ValidateUser(model.Login, model.Password)) always false

    Reply

Trackbacks & Pingbacks

  1. […] missed out a lot of code.  If you want to create a log-in page, then I suggest you read, How To Create a Log-in Page With Umbraco 7 which will fill in all the […]

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *