Extending ApplicationContext

Extending ApplicationContext

Old forum URL: forums.lhotka.net/forums/t/1393.aspx


SonOfPirate posted on Wednesday, October 04, 2006

We are interested in extending the ApplicationContext object so that we can throw in some application-related properties and give our application code access in a concise unified manner but we are struggling to figure out how to do this.

We've done something similar in the past with the HttpApplication class by creating our own class, inheriting from HttpApplication and reassigning the Global class (Global.asax) to inherit from our class rather than System.Web.HttpApplication.  Only problem is that I really don't know how it works.  What I mean is that asp.net/IIS control instantiating the object, so there was nothing to making this happen other than injecting ourself into the existing mechanism.

We'd like to be able to do a similar thing so that when we call ApplicationContext we are actually getting an instance of our class, inherited from ApplicationContext, and exposing our additional properties.

A perfect example of what we want to add are additional configuration properties and settings that are not part of the framework but for the application instead.

Any thoughts?

 

RockfordLhotka replied on Wednesday, October 04, 2006

The mechanism for doing this is to put your app-specific object into one of the ApplicationContext collections (GlobalContext, LocalContext, ClientContext).

The challenge is that ApplicationContext itself never moves (from client to server or back). Only the collections it contains are moved (or not, in the case of LocalContext).

Now ApplicationContext itself is a static class/Module - which explains why it doesn't move - but also means that you can't subclass it...

However, you could create a new static class/Module and have it delegate to ApplicationContext - then just use yours instead of the CSLA one. Since all the methods/properties are, by definition, Shared/static, this technique should work very nicely, with no real performance overhead.

kids_pro replied on Monday, December 04, 2006

I am running into the same situation.
Are there any sample code to solve this problem?

cds replied on Monday, December 04, 2006

Very simple... just do something like this:

    public static class ClientGuid
    {
        public const string ClientGuid_Key = "ClientGuid";

        /// <summary>
        /// Gets the GUID of this client.
        /// </summary>
        /// <value>The this client.</value>
        public static Guid ThisClient
        {
            get { return (Guid) Csla.ApplicationContext.ClientContext[ClientGuid_Key]; }
        }
    }

Then in my code, I can get type-safe access to the client's GUID simply by using

   ClientGuid.ThisClient

whether I'm at the client or the server.

This code assumes that at some point in the past I've put a GUID into the ClientContext collection on the ApplicationContext - you could just as easily provide a set method as well.

HTH

Craig

kids_pro replied on Monday, December 04, 2006

Dear Craig,

That exactly what I've done.
However this approach seem to work well in the ASP.NET app until I login in the Csla.ApplicationContext.ClientContext[ClientGuid_Key] become null reference.
I don't know what happen but I found that the code in Global.asa

    protected void Application_AcquireRequestState(
       object sender, EventArgs e) {
        if (Csla.ApplicationContext.AuthenticationType == "Windows")
            return;

        System.Security.Principal.IPrincipal principal;
        try {
            principal = (System.Security.Principal.IPrincipal)
              HttpContext.Current.Session["CslaPrincipal"];
        } catch {
            principal = null;
        }

        if (principal == null) {
            PID.BusinessObject.Security.PIDPrincipal.Logout();
            Csla.ApplicationContext.ClientContext["Language"] = "EN";
        } else {
            Csla.ApplicationContext.User = principal;
             /* I have to reset the variable after I  here otherwise it will return null reference */
            Csla.ApplicationContext.ClientContext["Language"] = "KH";
        }
    }  

However I still have problem with ClientContext now I switch to GlobalContext and still make the modification to the
Application_AcquireRequestState shown above and my problem gone away.

I am not sure if it the right way to store user preference in the ApplicationContext or I should switch to use ASP.NET build in user profile, ProfileBase.

Regards,

RockfordLhotka replied on Monday, December 04, 2006

kids_pro:


However this approach seem to work well in the ASP.NET app until I login in the Csla.ApplicationContext.ClientContext[ClientGuid_Key] become null reference.
I don't know what happen but I found that the code in Global.asa

As I said in a previous post, ClientContext only flows from client to app server, not the other direction.

But if you are in a web setting for the "client", it is important to remember that ASP.NET is stateless. Very clearly nothing you keep on a thread or in HttpContext survives from page request to page request - that's the nature of ASP.NET.

I suggest you use Session, the user's profile, or reload the lang setting on each page request using a ReadOnlyBase-derived object.

Copyright (c) Marimer LLC