mheptinstall mheptinstall - 1 month ago 12
ASP.NET (C#) Question

Auto-populate CreatedByUserId in MVC5 models

I have an ASP.NET MVC5 CRUD application that is using Windows Authentication and the site is secured by an Active Directory group, all members in this group have the same permissions. I am using Entity Framework 6 to access the database.

I have a very basic

User
model at present where
Login
would be
DOMAIN\username
. All my models reference this model via
CreatedByUserId
property, I've omitted the relationships to other models below.

public class User
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }

[Index(IsUnique = true)]
[MaxLength(100)]
public string Login { get; set; }

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedDatetime { get; set; }
}


I want to be able to achieve two things though I am not sure how without repeating code in all my controllers:


  1. Users that are authenticated via the Active Directory group have a User model created and stored in the database, if it doesn't already exist.

  2. When new items are created the
    CreatedByUserId
    is populated with the
    Id
    of the
    User
    performing the action.



I believe the first part could be achieved via a global
AuthorizeAttribute
filter that would create a new
User
if they didn't already exist and retreive the
Id
when they do, but where should this be stored for future reference.

The second part I am not sure on, I believe it is possible to do this without having to keep querying the database based on the current user. Could this value be set via a constructor using the
Id
retrieved when the
User
accesses the site?

Answer

The custom Authorize attribute sounds like a good idea. You can verify that the user is authenticated and check that they are a member of the authorized group. I would suggest that you don't need to store their id separately. Their logon will be available throughout your application via

HttpContext.Current.Request.RequestContext.HttpContext.User.Identity.Name

In your DbContext you can override SaveChanges() and access the user's identity.

Here is a good link to get you started Overriding SaveChanges and setting ModifiedDate, but how do I set ModifiedBy?

In your authorize attribute you could do something like this:

protected override void OnAuthorization(AuthorizationContext filterContext)
{
    // Get user id (create if not exists) using 
    // filterContext.HttpContext.User.Identity.Name

    // Set  generic principal using Id
    IPrincipal principal = new GenericPrincipal(
    new GenericIdentity("myuserid"), new string[] { "myrole" });

    HttpContext.Current.User = principal;
}

Then your user id will be accessible anywhere the old DOMAIN\Username value was

Comments