views:

257

answers:

3

Hi all,

I've got my application here where literally every object has a lastUpdatedBy property. The information I put into here is the person's username, which is retrieved from the session("username") variable.

How can I pass this data to my DAL in the class library?

At first I was just passing in the value into each method, but this is ridiculous I thought, there should be no reason to do that every time a method is called.

Then I thought well if I just put it in a constructor for each of the DAL related classes, that will make it even easier.

However, even still on any given page, I've got a plethora of New() declarations, for which every single line I need to pass in the session username casted as a string.

Is there an even still more efficient way of doing this so that I could only declare this in one place, and everything will know what it is and I can pass it to classes in a class library?

+1  A: 

There are several ways to go about it.

One is to have a class, that retrieves the value from session for you. Like Session.Current.Username, with Current being a static property that returns a session instance and Username being a simple property of Session.

Another one is to use dependency injection. You'd still have the input in the constructor (a class preferably instead of the simple value), but you wouldn't need to explicitly pass it on your code as its automatically injected.

eglasius
here's a good link to demonstrate your first point: http://www.codeproject.com/KB/aspnet/session_facade.aspx
derek
Could you provide an example of your second suggestion? I am confused as how I would do this since the class library cannot use session, but I have done dependent injection. On my DAL class I would have a constructor with one parameter, a class that returns the session variable, which sets some variable in my DAL class to the session variable, now you said use a class instead of the value, but how is this possible? It would still be a class in the class library, which can't access session.
sah302
@sah302 I meant inject a class like you described (i.e. its awful, but u can also inject the literal string value instead). In the DAL you declare an interface with that describes what you need your DAL to receive, the actual implementation won't be in your DAL. On a higher layer where you have access to the context / session you'd implement it, and that's what you inject.
eglasius
@Freddy Rios Also I am not seeing how the first example would either because I can't use Session in a class library, the example in the link allows me to create a class like you mentioned, but I would have to create that class in my application, not class library so I would still have to pass it to my class library in some way? Or am I misunderstanding?
sah302
@sahk302 you can use httpcontext in the class library, but in that case you have to add a reference to System.Web.dll to the library project. Injecting the dependency avoids doing that as you noted.
eglasius
@Freddy Rios, this doesn't work for me, the only option I have are: AspNetHostingPermission, AspNetHostingPermissionAttributes, AspNetHostingPermissionLevel after System.Web., I also tried just System.Web, that also did not provide it.
sah302
@Freddy Rios, Okay I got it, would it be proper to use a module? Using VB so no static....could you write an example class for what you said in number one? I see what you mean, but am not sure how to do it.
sah302
@sah302 number one is just like in the link derek posted, under "An Example Session Facade Class". I'm used to c#, if it helps "Static" in vb is "Shared" so I'm sure you can do the same you can like that class.
eglasius
@Freddy, got it. I guess I am not supposed to be able to unit test this though? I always get Object reference not set to an instance of an object when it gets to the HttpContext.Current.Session("Username") line when trying to unit test it, but if I use it on an actual page, it works, even if Session("Username") is blank. This is happening because the HttpContext.Current.Session isn't created until runtime and is expected behavior correct?
sah302
@sah302 technically you can unit test stuff that depend on httpcontext but is a PITA. Using DI lets you unit test it easily i.e. interface + separate implementation, so when you unit test it you use a mock against that interface.
eglasius
A: 

I would create an AbstractDALObject abstract class that contains a string Username property. Make all of your DAL classes derive from this abstract class, and instantiate them by creating a DALFactory class that sets this property. Your DALFactory class would either contain a CreateXXXDAL method for each type of DAL, or you could use reflection to create a generic method like below:

    private HttpSessionState m_Session = null; //set in constructor

    T CreateDAL<T>() where T : AbstractDALObject {
        Type t = typeof(T);

        //fetch a zero-param constructor 
        //you could change the argument types if you have a 
        //standard for the class
        ConstructorInfo ctor = t.GetConstructor(new Type[0]);

        T myDAL = (T) ctor.Invoke(new object[0]);
        myDAL.Username = m_Session ("Username");

        return myDAL;
    }
MrGumbe
The above wouldn't work because a class library project cannot use Session
sah302
Implied is that the factory object would have a private variable of type HttpSessionState set by the calling page. Another option would be to make the session state object a parameter of the method (this would allow you to make the method static). Please reconsider your vote, as I believe this will present you with a very workable solution.
MrGumbe
I didn't give you the negative vote ><.
sah302
Well shoot, I wonder who did. Giving someone a negative vote w/o explanation is just rude :-)
MrGumbe
A: 

I would generally take steps to ensure that Thread.CurrentPrincipal references the currently connected user. This will be done automatically in some cases:

  • an ASP.NET application that uses the ASP.NET RoleManager

  • a WCF service hosted in IIS that uses principalPermissionMode ="UseAspNetRoles"

In other cases, you may have to do it yourself (e.g. at application startup in a WinForms application).

Then your DAL can simply use Thread.CurrentPrincipal.Identity.Name to identify the current user.

This is cleaner than using HttpSessionState, which implies a dependency on ASP.NET.

Joe