Q:

Admin login user controller

I'm trying to implement a simple login for admin in a MVC3 project. I'm new to ASP.NET and to MVC3. I have googled and asked questions! have seen a lot of really nice ways of implementing this but they were all on a very abstract level and quite frankly maybe a bit to high for me at the time being. I have the credentials in my db so basically I just want to query that one and redirect the user if login matches those and if not show login form again. So this is what I got. My model:
  public class FormModel
{
    public bool isAdmin { get; set; }

 [Required(ErrorMessage = "Please enter your Username")]
 //[Remote("ValidateUserName", "Login", ErrorMessage = "UserName already taken!")]
 [StringLength(6, MinimumLength = 3)]
 [Display(Name = "Username:")]
 [RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")] 
 public string UserName { get; set; }

 [Required(ErrorMessage = "Please enter your Password")]
 [DataType(DataType.Password)]
 [Display(Name = "Password:")]
 public string Password { get; set; }

}
 public User IsAdmin(string username, string password) 
   { 
      return (from user in db.Users 
      where user.username == username && user.password == password <--- alternative here is to just match username and pass against the data I have in my db columns(testdata 'admin', 'password')
      && user.IsAdmin == true  
      select user).SingleOrDefault(); 
    }

And in my controller basically this right now:
   public ActionResult Index()
    {
        //some code here maybe a conditional
        return View();
    }

And finally my view:
     @model Web.VoucherCannon.Models.FormModel
     @using (Html.BeginForm("HandleForm", "Login", FormMethod.Post, new {id = "myForm"})) {
@Html.ValidationSummary(true)
        <div class="editor-label">
        @Html.LabelFor(model => model.UserName)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.UserName)
        @Html.ValidationMessageFor(model => model.UserName)
    </div> 
    <div class="editor-label">
        @Html.LabelFor(model => model.Password)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Password)
        @Html.ValidationMessageFor(model => model.Password)
    </div>
    <button class="button">Log In</button> 
      }

So now. How do I use the returned result of the query in my controller so that I can login? I'm sure I will refactor this later on and make it with a dbcontext layer and so on, but just for now I will be happy to make this work. Grateful for help!

A:

You should have 2 controller actions: one for rendering the login (accessible on GET) form and one for handling the submission (accessible on POST) and performing the actual authentication.
// This will render the Login view (the one you have shown)
public ActionResult Login()
{
    var model = new FormModel();
    return View(model);
}

// This one is responsible for handling the submission and credential verification
[HttpPost]
public ActionResult Login(FormModel model)
{
    if (!ModelState.IsValid)
    {
        // The user submit the form but validation 
        // (as defined on the model using DataAnnotation attributes) failed
        // => redisplay the view so that the user can fix his errors
        return View(model);
    }

    // notice that you don't need to pass parameters to the IsAdmin method
    // as it already contains the username and password as properties
    if (!model.IsAdmin()) 
    {
        // The IsAdmin method didn't verify the credentials => add a model error
        // and redisplay the login view
        ModelState.AddModelError("username", "dude you are not an admin");
        return View(model);
    }

    // OK, at this stage everything is fine => we can grant access
    // by issuing an authentication cookie
    FormsAuthentication.SetAuthCookie(model.UserName, false);

    // finally we redirect to some home page for admins
    return RedirectToAction("Index", "Admin");
}

