views:

242

answers:

3

WHen submitting data to Data Layer when userID is not a field in the object being passed, but will still need to cross reference tables with userID when submitting data, should I call the the membership class to get the UserID at the datalayer, or should I pass UserID from level to level as a parameter? (ie from the business layer to the data layer? ) (Or does it not matter either way?)

Controller or Business Layer:

 MembershipUser user = Membership.GetUser();
 Guid userID = (Guid)user.ProviderUserKey;
 DL.SaveObject (Object, userID);

OR

Do it in DataLayer:

SaveObject(Object)
{ 

 MembershipUser user = Membership.GetUser();
                Guid userID = (Guid)user.ProviderUserKey;
 ...
 ...

}
+1  A: 

In general I'd prefer to see GetUser() in SaveObject(), since that would allow the business layer to be abstracted away from it and should reduce the amount of code that is calling GetUser(). But it depends on the requirements. If you needed to apply business rules based on who the user is, then (also) putting it in the business layer might make more sense.

Authorization/authentication is one of those cross-cutting concerns that AOP (aspect oriented programming) is best suited to handle.

Update: CraigTP makes a valid point wrt having the data layer be agnostic about where its data comes from. In general I would agree. In this scenario there is a requirement where user identity is needed by the data persistence mechanism, probably for security and/or auditing purposes. So in this case I'd prefer to put the user identity access call under the control of the layer that needs it. I'd abstract away the details of the GetUser() implementation behind another call, so the data layer doesn't have a dependency on System.Web.Security.

Lee Harold
+2  A: 

Whilst this is indeed a cross-cutting concern, my personal preference is that code such as:

MembershipUser user = Membership.GetUser();
Guid userID = (Guid)user.ProviderUserKey;

should NOT be in the data layer.

I like to see this kind of code in a layer higher than the data layer, usually the business layer, simply because I want my data layer to be entirely agnostic as where the data it will read/write/process has come from. I want my data gathering to be done primarily in the UI layer (in the case of user supplied data/input) and perhaps a little more data gathering within the business layer (such as gathering a UserID or retrieving a user's roles/authorisation).

Putting code such as this in the business layer can potentially lead to duplication of this code across many different domain objects, however, this can be alleviated by abstracting this code away into it's own object, and using object composition to allow other domain objects to access it.

CraigTP
+2  A: 

Passing input to the DataAccessLayer should be done by the controller or BL. I prefer not to include anything other than Data read / write in DAL. (in this case, DAL is given the task of determining the currently logged in user)

Ramesh