8
votes

I'm using the default ASP.Net MVC template in Visual Studio. I'm using the ASP.Net Identity code that was created for me in the template. I'd like for the DBContext I use to be aware of the relationship between the ApplicationUser entity (AspNetUser table) and the rest of my entities. For example, I want to be able to have an ApplicationUser.Messages property that exhibits the relationship between the ApplicationUser and Message entities. I have my DbContext for all non-Identity entities in a Data Access Layer project. And the template ApplicationDbContext is in the UI Layer. In order to keep the relationships between the Identity entities and my custom entities, I need to merge into one DbContext, right? How do I do this?

Here is some sample code of what I have:

The IdentityUser and DbContext created for me in the UI Layer project from the MVC template with my custom Messages property:

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

    public ICollection<Message> Messages { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

The Message class I have in my Domain/Business Logic Layer:

public class Message
{

    public int Id { get; set; }

    [Required]
    public string Title { get; set; }

    [Required]
    public string Body { get; set; }

    [Required]
    public DateTime Created { get; set; }
}

The DBContext I have in my Data Access Layer project:

public class PSNContext : DbContext, IPSNContext
{
    public PSNContext()
        :base ("DefaultConnection")
    {
    }

    public DbSet<Message> Messages { get; set; }
}

It doesn't feel right to bring UI-specific code like this from the ApplicationUser in the UI Layer into my Business Logic Layer:

var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

Is there a better way to do this?

1
The question is right. I am facing the same issue. I don't want to maintain two DbContexts , one in UI layer and another in my DataAccess Layer. If I move the ASP.NET Identity classes to the DataLayer, I have to move the System.AspNet.Identity namespace to DataLayer as well and I want my Data Layer to be independent of the UI technology. Is it correct to have a namespace "AspNet" in Data Layer?Balaji Birajdar

1 Answers

2
votes

This has already been answered here

With regards to moving ApplicationUser into a logic layer, I personally think it's fine. The logic there does not make use of Web specific namespaces. The ones in use are Microsoft.AspNet.Identity and System.Security.Claims related. In this instance ApplicationUser is the entity, your web layer should be using ClaimsPrincipal for authentication and authorization.

If you'd like an example, I've previously done this merge before. Although it's not in an ideal state, it should serve as an example for what you are trying to achieve.