Consider the following architecture: ASP.NET MVC Application having controllers which depend on service classes (MembershipService, EmailService etc.) which in turn depend on data access context (custom DbContext).
namespace App.Services
{
using System;
using System.Linq;
using App.Data;
using App.Security;
public interface IMembershipService
{
void ValidateUser(string userName, string password);
}
public class MembershipService : IMembershipService
{
private readonly DatabaseContext db;
public MembershipService(DatabaseContext db)
{
this.db = db;
}
public void ValidateUser(string userName, string password)
{
if (string.IsNullOrWhiteSpace(userName) || userName.Length > 128 ||
string.IsNullOrWhiteSpace(password) || password.Length > 256)
{
throw new ApplicationException("The user name or password provided is incorrect.");
}
var user = this.db.Users.SingleOrDefault(u => u.UserName == userName);
if (user == null || !PasswordHash.Validate(password, user.PasswordHash, user.PasswordSalt))
{
throw new ApplicationException("The user name or password provided is incorrect.");
}
if (!user.IsApproved)
{
throw new ApplicationException("Login failed. Your account is not approved.");
}
user.LastLoginDate = DateTime.UtcNow;
this.db.SaveChanges();
}
}
}
Usage sample:
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (this.ModelState.IsValid)
{
try
{
this.membershipService.ValidateUser(model.UserName, model.Password);
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return this.RedirectToLocal(returnUrl);
}
catch (ApplicationException ex)
{
this.ModelState.AddModelError(string.Empty, ex.Message);
}
}
// If we got this far, something failed, redisplay form
return this.View(model);
}
Taken from http://github.com/kriasoft/site-sdk