Chris
Chris

Reputation: 361

Multi user application

I am building a web app for learning purposes and it will be a multi user application. Each user will have their data. I am not 100% certain on how to implement this. Should I have Model1 include an int UserId {get;set;} property to hold the user GUID or should it be of type IdentityUser? Then in my controllers do I always take into account the current logged in user id for my queries? I should be able to get the userId from the session?

Upvotes: 0

Views: 254

Answers (2)

Chris Pratt
Chris Pratt

Reputation: 239300

For some reason people seem to get intimidated when it comes to the user object, but it's no different than any other type of relation. Yes, if a particular entity is "owned" by a user, then there should be a foreign key to the user entity.

I'm assuming you're already using ASP.NET Identity, since you mentioned IdentityUser, but you seem to be confused about how Entity Framework works with relationships. Technically, either of the following two properties will have the same net effect on the generated table (e.g. a column named User_Id:

public string User_Id { get; set; }

OR

public virtual ApplicationUser User { get; set; }

In the second line, Entity Framework sees that you're relating another entity, so it takes it upon itself to create an implicit foreign key to track that relationship. It's not part of your entity, but it's on the database table regardless. This is because Entity Framework obviously can't store an entire user object in a single column at the database level, nor would you want it to.

That said, the code you should use for the relation should actually look like:

[ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }

This does two things:

  1. You get a navigation property User that allows you direct access to the user object through this entity, while also informing Entity Framework that there's a relationship between entities that needs to be tracked here.

  2. You have an explicit foreign key property UserId that allows you actually get at the foreign key if you need to. This is often necessary if you want to be able to do things like pick a related item from a select list, as the select list can only post a primitive type like an int or string. If you didn't have this property, it would be must more difficult to achieve this type of scenario.

Technically the ForeignKey attribute isn't strictly required, as Entity Framework will pick up that UserId is the foreign key for User by convention. However, I think it's always better to be explicit about what you expect to be happening, and in scenarios where the convention may not be just right, the habit of using ForeignKey will make sure that things still work as they should.

Finally, as to authorization, yes, you would filter entities by user, so that each user only sees what they should see. For example:

var widgets = db.Widgets.Where(m => m.UserId == User.Identity.GetUserId());

Or, in a situation where you're showing or allowing the user to edit a single item:

var widget = db.Widgets.SingleOrDefault(m => m.Id == widgetId && m.UserId == User.Identity.GetUserId());
if (widget == null)
{
    return new HttpNotFoundResult();
}

With that, the user doesn't even have visibility into what other "widgets" may be in the application. If it's not theirs, they get a 404 just as if it didn't event exist.

Upvotes: 2

landers
landers

Reputation: 105

Try to think of all of the scenarios. Do you think there's a possibility of shared logins? Users needing access without a login or multiple logins can also cause problems. Using the UserId is a good solution in most cases, but make sure you know who's using it and how.

Upvotes: 0

Related Questions