Archive
Monthly
Go
|
|
DNN Blog
Sep
7
Posted by:
Peter Donker
9/7/2008
All DNN requests run within what’s known in an HttpContext, i.e. a context of an http web request. I say all, but this is not entirely true. Nearly all DNN requests run through HttpContext. There are a number of circumstances under which your code will not run within an HttpContext. This can be because the code runs as a result of a scheduled service or because you’ve decided to spark off a new thread. If you do have code that runs outside HttpContext, there is an evil ‘bug monster’ lurking in the core. This is the PortalSettings object. More specifically, the GetCurrentPortalSettings static method on this PortalController that returns this object. Allow me to explain.
What is the PortalSettings object? It is a collection of parameters that define in which DNN portal context the user is. So this includes most of the parameters set by the Administrator under the Site Settings, but also some context parameters such as the HttpAlias (remember that a single portal can respond to/have multiple aliases). The portal settings are made in the Url rewriter module. The latter is a piece of code that runs on every regular Http page request to DNN. It analyzes the url and distills the correct portal from this. The portal parameters are loaded and the extra contextual variables are added to this. The whole object is then stored in the variables that all subsequent code that runs in that thread can draw from. The GetCurrentPortalSettings method draws this object from the place it is stored.
So what is the PortalSettings used for? Well, in short it is used all over the place. It is the default method to find out what the current portal is, amongst others. If you search in the DNN source code for usages of GetCurrentPortalSettings you’ll get a very, very long list of calls.
So what’s the issue? The issue is that outside the HttpContext the PortalSettings object is not available. “A”, I hear you say, “that makes sense as we have no HttpAlias”. Well, yes and no. Sometimes we need to access portal settings from our code that is running outside the HttpContext. It is quite thinkable that I have a PortalID and I’d like to have my Portal’s Settings. Hmm, but we have the PortalInfo object, no? The PortalInfo is a lot like the PortalSettings. It is the container for the settings under Site Settings, so it only misses the contextual info like the HttpAlias. Correct. We could use this object to access our settings. But unfortunately a lot of DNN methods rely on the PortalSettings object. So many (and I mean a lot) of calls to the framework will start to throw exceptions. The aforementioned usages list underlines what the extent is of this ‘problem’.
To add to the predicament, later (I believe post 04.06.xx) versions of the Url Rewriter no longer set the PortalSettings object if the call is not to a DNN or other aspx page. I was once faced with a lot of rewriting as I was using an .axd extension to handle some calls to my code.
An illustration
I have a scheduled task that checks in the database for notifications to be sent. For these notifications I use token replace and a url to the site. The url needs an HttpAlias so this immediately brings home the problem. But DNN’s token replace (used to personalize text blocks) heavily relies on the PortalSettings object. This object is unavailable as it is a scheduled task.
Solutions?
The solution to this problem is not easy. My first thought was:
1. Introduce a site setting where the preferred HttpAlias is set. Admins set this and are aware that for instance emails sent outside HttpContext will link back to this address in my example.
2. GetCurrentPortalSettings gets a sister where you specify a PortalID. If the PortalSettings have already been constructed and the IDs match, then use those. If not, than reconstruct.
3. Start carrying the PortalID throughout the code that relies deep down on the PortalSettings object
Point 3 above is probably the most problematic of the changes. It will change the signature of many methods.
Another approach would be to ‘kick’ DNN to set the PortalSettings in the current thread. You could have a method SetCurrentPortalSettings which takes a portal ID and sets the object that all subsequent calls can use through GetCurrentPortalSettings.
Conclusion
In my opinion the reliance on PortalSettings within the DNN framework is such that we need a proper way to have them outside an HttpContext.
10 comment(s) so far...
Re: DNN Outside HttpContext limitations
Correct me if I am wrong but most to all of that information is one way or another saved in the database. So if your trying to run scheduled events and need to have this information you just need to make the calls to the database to get the information you want. Now granted it would be really nice to just use the token replacement methods, its still possible. For example I made a small module for work. The module allows an end user to type in a basic email, use the replacement tokens and pick how often to send the email to the users. Daily, weekly, etc. When they hit submit on the module, I store the values for the replacement tags. IE if I see [portalid] replacement tag. I have the module store that in its table. When I send the email out I have a DB join that pulls the actual value out of the database and fills it in.
Now to save me some overhead work. I did limit my users to only a few options like url / portal id / etc. Cause I really didnt want to code all the parts for each replacement tokens, however at some point I hope to expand it.
Overall though, point is since you can't "schedule" anything inside DNN without having a class / assembly anyways, why not use that class / assembly to manage all the information you want via the database. How you make it user friendly is your part. So to me its less of a limitation and more of a nick nak haggle. While I disklike it as well, just not sure there is going to be a better way to do it. The only solution is to provide "static" access to the values, however they are already there in the database. Just a matter of how / when to access it.
And forgive me if I completely mis-read what you are trying to do/are saying.
By keeperofstars on
9/8/2008
|
Re: DNN Outside HttpContext limitations
@keeperofstars
I'm not sure if I'm on the same page here. The issue is that TokenReplace (which is a really cool and powerful new feature) is an illustration of my point that the framework is riddled with calls to PortalSettings and that this object is not available to me outside the http context. There are many more parts of the framework that rely on PortalSettings. True the DB holds some stuff, which is what you'd use the PortalInfo for. But that is a workaround for 50% of the cases I dealt with. In other cases I end up rewriting DNN framework code to catch the call to PortalSettings.
Just another note on the TokenReplacer. If I understand correctly you use your own token replacement, which is understandable. I have begun to move all my code to use the TokenReplace however, as it is very elegant. I implement the interface on all my objects now. The use case extends far beyond email personalization. So in this case, it'd be sad to redo this stuff in my own module when it is done so well in the core.
Peter
By donker on
9/8/2008
|
Re: DNN Outside HttpContext limitations
I see, and yes we are on a bit of a different piece. So you are saying you want to be able to use token replace for things, but do it when the page is pretty much not active. So the built in token replace calls will work just as seemless as if you were actively viewing the page?
By keeperofstars on
9/8/2008
|
Re: DNN Outside HttpContext limitations
Peter,
Is there a solution to this coming with the Cambrian release ? I understood there was a move towards interfaces that would help in these cases. We need to break those hard dependencies!!!
Thanks for raising the issues.
Jim
By jbonnie on
9/8/2008
|
Re: DNN Outside HttpContext limitations
There is a move towards interfaces but we have not dealt with this issue per se in the Cambrian codebase at the moment. Given where we are in the release process it might be doable in 5.1.
The real problem is that the common call PortalController.GetCurrentPortalSettings() is just fetching the settings from the HttpContext, which is null outside the web environment.
There are more overloads for creating new Portal Settings that could be used outside of the context - which may alleviate things.
By cnurse on
9/8/2008
|
Re: DNN Outside HttpContext limitations
@Charles:
Couldn't the object be stored in the Thread (instead of HttpContext) in a way that'd work for both scenarios? The only change to the core would be where the PortalSettings are put and GetPortalSettings. Then we could add a method that would 'put' the PortalSettings in the current thread given a PortalId which can be called from a scheduled task.
I'm not sure but the Thread looks like it has a store with GetData and SetData.
Peter
By donker on
9/8/2008
|
Re: DNN Outside HttpContext limitations
Peter, tokenreplace checks the HttpContext for nothing in DNN5.0, I run into the same issue some months ago.
By cshark on
9/8/2008
|
Re: DNN Outside HttpContext limitations
Hi, some workaround maybe could also be accomplished by using the ScheduleItemSettings, mentioned in the DNN Scheduler Documentation. Unfortunately, there seems only to be a function to get them, not to set them. I use objPortalController.GetPortal() to get me a PortalInfo object, that helps a bit.
By felixhelix on
10/21/2008
|
Re: DNN Outside HttpContext limitations
Felix, I use PortalInfo as well, but it is incomplete with regards to PortalSettings. But the real problem here is that so many objects in the core use the httpcontext somewhere through calls to other objects/methods etc.
Small udate: I discussed this briefly with Charles Nurse and others at OpenForce EU. Obviously I did not expect someone to pull a white rabbit from a hat and show a way out of this mess. But I'm happy it was recognized and acknowledged. It brought about a discussion on another matter: the age of the scheduler. It turns out there are more issues with it that need resolving and maybe it will get an overhaul soon.
By donker on
10/21/2008
|
Re: DNN Outside HttpContext limitations
Hi Peter,
I hit the same issue (I am doing localization, token replacement etc.) in the scheduler and got around it using Bruce's suggestion: www.ifinity.com.au/Blog/Technical_Blog/EntryId/52/Creating-PortalSettings-Instance-running-in-a-DotNetNuke-Schedule-Item
Works well now but yes, this area could be improved!
By Rodney Joyce on
5/25/2009
|
|