Question:
Normally, one accesses the session object like this:
Session["foo"] = "bar";
I have written a wrapper over it, which is generic, and which checks whether a session has expired or not, and throws a SessionExpiredException if that is so.
In order to use my session access, I have to access sessions over my class like this
WebApplications.SessionAccess.Set<string>("foo", "bar");
Now, obviously, despite the presence of the class SessionAccess, one could still access the session via the normal session object. This is not desirable, and additonally, I want to later include it in a larger old project which has been written using the normal Session, which would mean I would have to replace all calls to session (a number in the low thousands) with my wrapper.
Is there a way I can overwrite the System.Web.HttpSessionStateBase.Controller.Session - Property with my own ?
The thing is, without a custom session handler defined in web.config, because there sometimes already is one for using the database for sessions (one could still initialize a module in Global.asax).
Those NULL-Reference exception YSODs on SessionTimeout are hyper-disturbing.
If possible, a solution that works on classical ASP.NET web-forms as well as on MVC.
I don't think that there will be any full-proof solution as you wants it but few tricks can make your life easier.
Create yet another wrapper that provides indexer property so that you can easily substitute calls such as Session["key"] = "name" to your wrapper property;
You need to inherit all your pages (i.e. code-behind classes) from a common base page class (that itself has inherited indirectly from System.Web.UI.Page). If you already have such base page then you are really in good situation. Inherit your common page base class from an internal base class that itself inherited from System.Web.UI.Page.
In the common page base, add a new Session property that would return your wrapper object created in #1. Similar trick has to be done for UserControl (and custom control) if you have many of them. This will save you from replacing the most of Session["key"] = "name" kind of calls.
Finally, override Session property in the internal base page class to add a debug assertion. You may choose to return null but that would break production usage. Debug assertion is a lot better to find session usage that will be escaped from #3.
As said, this is not a full-proof solution as one can still access the session state via HttpContext. But it should make the migration of legacy code to your session accessor object easier.
Related
Imagine some SOA. We have a few different services, of which the OperationContext is extended by some SecureOperationContext which makes sure certain security demands are met.
Assume furthermore that sometimes we might need to know a certain property from this SecureOperationContext somewhere else, in a place where there is and won't be this SecureOperationContext. For example a username for some sort of logging purpose.
Currently we're using something that looks and smells plain dirty. The fat's dripping of in my opionion.
Now, in some 'Common' library, there is a class defined with a ThreadStatic property: Username. I guess you can catch my drift: the security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This thing bugs me, but on the other hand what else to do? I was thinking about creating a method that takes a string as parameter to handle this, but then all my methods need to still read that username property, which is non-dry.
So on one hand, this way everything is handled on the background, but I'm not just quite happy having to maintain some (global) class just to achieve this.
Any tips?
I'm not sure how to put it in less abstract terms, but here goes (in pseudo).
public WebService
{
public Save(Car car)
{
// Some SecurityCOntext is known here, this holds top secret info,
// like the username
// and sets this into the golbal helper class UserNameManagemer
// car has for example a CreatedDate property (from an Interface),
//but I don't want handle do this propertyin every Create method can handled in some general piecei of code.
efcontainer.AddObjcect(car)
e.SaveChanges() ->
//Now savechanges will check the objects in the ObjectSatateManager
//and sets the apppriopriate property via the global thing.
}
}
Now what to do to rid myself of this global variable!. Passing a username to SaveChanges is undesirable ass well, since we'd then still have to manually repat this for everything, which blows.
Encapsulate the global property in a service. Define an interface for that service. Now, depend on that interface everywhere you need the data by having a constructor parameter of that type.
This is called dependency injection and is a very important concept when you want to avoid problems as the one you currently have. A dependency injection container such as Autofac can help if you have a big application, but is not strictly required.
The most important thing is to understand dependency injection and have a well-defined composition root, no matter whether you use a DI container or do it yourself.
The security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This sounds like the data is determined dynamically. Note that you can still use a service to track the value. That service also knows whether the value is available or not. This way, you can better manage the temporal coupling that you have at the moment.
Edit: You can further improve the design by creating the client objects through a factory. That factory can ensure that the value is available, so it couples the lifetime of the client objects to the availability of the value. This way, you are sure to always act in a context where the value can be safely accessed.
I have a number of types for which I need to provide custom functions that talk to the external world.
For example, I may have a Widget, and a Sprocket, and when data from the world that I don't control arrives and says "make a Widget," then I need to call a Widget.Create() function.
If the world says "make a Hammer," then I need to return a "Hammer does not exist" error.
However, the mapping between world-representation and type-name is not 1:1, so I can't simply use reflection to find the type name directly -- I need a table. (In fact, "name" may for example be a specific integer value.)
I understand how I can use a pre-defined table (or Dictionary) that maps from world-representation to class-name.
I also understand how to extend/change this table at runtime if the set of possible classes changes. (Because of rules changes, or dynamically loaded parts of the application, or whatever.)
However, all of that requires duplication -- I have to both implement my class, and then, in some other place in the code, remember to add an instance of "this class has this name in the external world."
This is a bit of a code smell, because sometime in the future I will write a new class (or delete an old class) and forget to update the table, and then spend time debugging why it doesn't work right.
I thought I could use a static member in each class which registers itself in a global table:
public static Registration Me = new Registration(typeid(MyClass), "My Name");
Unfortunately, static fields are not initialized until some function in the class is executed/accessed, so this doesn't run at start-up. (Static constructors have similar limitations, plus even more overhead in the runtime!)
The next idea was to decorate the class with a custom attribute that says "register this class in the table."
[Register("My Name")]
class MyClass : .... {
}
Unfortunately, the "Register" attribute doesn't know what class it is attached to -- only the MyClass class knows that it has the Register attribute. (This is infuriating to me, as it would be SO CONVENIENT if attributes knew where they were attached, in many, many cases. But that's an aside!)
So, the least bad implementation I can think of is to iterate all the types of all the assemblies, using reflection, and check whether they have this attribute, and if they do, register them in the table. This is, shall we say, neither elegant nor efficient.
Is there a better way to auto-register classes without having to update some other source file with a central registry?
You could also iterate over all classes matching some criteria and use RuntimeHelpers.RunClassConstructor to ensure the static initializers all get run.
Something like:
var baseType = typeof(MyType);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(baseType));
foreach (var t in types)
{
RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
This should ensure all your
public static Registration Me = new Registration(typeid(MyClass), "My Name");
functions get called.
I have checked with other resources (that are quite knowledgeable about the internals of the CLR and IL) and it seems that this is a hole in the CLR and the C# language. There simply is no direct way of making things automatically happen on assembly load or appdomain preparation. Walking the types and finding the types that I'm interested in is the least bad way.
In fact, attributes aren't always created until some piece of code asks for them, so I can't use an attribute constructor with a type argument to auto-register, either!
This is of course not great, because if there are eight different pieces of code that each have their own kind of registration they want to do, each of those pieces have to iterate through all of the types and do the inspection on their own. The only way around that would be to give up on modularity, and make all of the different "things" that happen to types be centralized to a single walk-all-types loop at the start of the app. Third party libraries (including the MEF) still wouldn't go inside this loop, though, so there's just an unavoidable chunk of overhead here, OR an unavoidable piece of duplication -- my choice, as developer.
Let's suppose I have a layer of abstract controllers, which delegates the request to its child controller class, until it reaches the implementation.
Think of it like a pipeline of controllers, that the request must go through, and includes caching the responses, authorizing and authenticating the user, validating the input and output data, handling repository access, etc.
My leaf class (the last child of the hierarchy), may have the following signature:
public class SeasonsController : DefaultPersistenceRestController
<int, Season, SeasonPutDTO, SeasonPostDTO, SeasonQueryData> {
/** Controller implementation here **/
}
The base classes have a lot of reusable code located in one module, this is good and has helped me a lot when changing the logic of my controllers at a global level.
Now, suppose SeasonsController need to call EpisodesController, for irrelevant reasons.
The call would be like this:
EpisodesController episodeController = new EpisodesController();
//Do something with EpisodesController
The problem is that I don't want EpisodesController to be accessed from the outside, such as client's request. ASP.NET automatically identifies controllers and creates a public endpoint for them, such as http://localhost:80/episodes.
I created EpisodesController because it uses a lot of logic from the controller's base classes, but I intend to use it internally.
I can desactivate authentication, authorization, cache and all other stuff that will be useless if a controller is used in this way, so that's not a problem.
However, I cannot manage to prevent ASP.NET to ignore my EpisodesController class, and to not consider it like a controller.
Is there an attribute or annotation maybe that will tell the compiler to do this? Maybe some modification in Web.config?.
Also note that I don't want to change EpisodesController's class name to another name, as it is really a controller, but an internal one.
You could try to use the IgnoreRoute extension method. Or you could try the internal as suggested by beautifulcoder. If it's in another assembly (and you can modify it) you could also make it visible to other assemblies with InternalsVisibleToAttribute.
Although to be honest, using one controller within another controller doesn't seem right to me. I would try and refactor you common functionality to services/helpers, then you could probably also make your EpisodesController into a simple service. Composition over inheritance and all that :)
If you make a controller public it will be accessible. From what I understand, you can change it to protected or internal.
I have a set of functions I want to be available to my web pages and user controls in my c# .net 3.5 web project. My standard approach for pages is to create a "base page" that extends the System.Web.UI.Page class and then have my pages inherit from this, rather than directly from the Page class.
I now want to expose some of these functions to my web controls (ascx) and web services. I can think of a number of ways to do this, but they seem a little clumsy and I think I'm missing a trick.
Is there an easy way to provide some common functions to both my pages, web services and controls using inheritance, or do I need to wrap these functions in a class that all of them can access?
An example to clarify:
I have a singleton that handles most functionality for my web application.
At the start of each request I want to check that the class exists in the web cache and initialise it if not.
Initially this was handled in a page base that the pages all used. Now I need to be able to access my singleton safely from services and controls, with the same checks. I have therefore extracted the checking and initialisation logic into another class, that then each of my base page, control and web service, all instantiate. Even with this model I have the same code repeated in 3 places (each of my base classes for controls, ws and pages), albeit not much code, this seems wrong too!
It works, but it seems clumsy...I look forward to you guys humbling me with your wisdom!
Sounds to mee like a case of aspect-oriented programming. .NET is ill equipped for this. I'm afraid that your solution is one of the best.
Alternatively perhaps you can move all or some of those functions to a static class/singleton and then use that class from your aspx/ascx/asmx? Not much in the way of inheritance, but at least less code duplication.
My solution to this is to put all the methods and functions I want to share in my base master page class. I then put an equivalent for each method and function in the user control base class as follows:
//Property in masterpage base
public string QsSearchTerm
{
get
{
if (!String.IsNullOrEmpty(Request.QueryString["q"]))
{
return Helpers.SanitiseString(Server.UrlDecode(Request.QueryString["q"]));
}
return String.Empty;
}
}
//Property in usercontrol base
public string QsSearchTerm
{
get
{
if (Page.Master is BaseMasterPage)
{
return ((BaseMasterPage)Page.Master).QsSearchTerm;
}
return string.Empty;
}
}
What this doesn't help with, is your code repetition with web service base classes. I would think that refactoring the above into a class with a constructor that accepts an HttpContext instance would be the way forward. You can then expose a singleton instance of this class in your base web service, master page, user control, page etc.
Hope this helps, but I too would be interested in hearing if there's a better way.
In your Singleton you could provide a Strategy interface to allow variations of the code depending on the configured environment. This would allow you to switch between web/windows/wcf...and so on.
I think using a BasePage is the right approach.
I have multiple base pages and custom user controls that load differently depending on which basepage is used by the current page.
In your custom user control you can use something like:
if (this.Page is BasePageName)
{
BasePageName bp = (BasePageName)this.Page;
bp.BasePageFunction();
}
No you can get ride of the repetitive code in the custom user control and just call it from the base page.
You can also have a hierarchy of inherited base pages depending on page functionality and needs. ie.) BasePageName2 : BasePageName
In my asp.net web app. I have three classes (inside app_code folder) under namespace WPP which are as follows:
1. wpp_Common
2. wpp_SQL
3. wpp_Admin
All these classes contains different functions which I am using in my application to accomplish different tasks. Such as, wpp_common contains a function which make my URL's SEO'd, and wpp_SQL have some functions which I am using to get details from database.
Now, I am using these classes on different web pages web pages and in web controls. To use these classes I am creating instances of all three classes on the page where I am using them.
protected WPP.wpp_Common ObjCommon = new WPP.wpp_Common();
protected WPP.wpp_SQL ObjSQL = new WPP.wpp_SQL();
protected WPP.wpp_Admin ObjAdmin = new WPP.wpp_Admin();
So, I want to know, is this a better and only way to access my classes by making seprate instances at every page, is this method have any performance constraints.
Or is there a better and logical way to access my classes from ASP.net web pages and web controls.
Thanks.
If these classes don't encapsulate anything mutable, it may be worth making the key methods utilized static. Then, you don't even need an instance of the class. This seems to make sense for your SEO class. The SQL class you may want a shared instance as it may contain a reference to some SQL connection/class, but this could also be a parameter in a static method.
What you're doing seems okay to me, though.
Really the answer boils down to the complexity of the class. If your classes are lightweight and have low initialization overhead, then you are probably OK with instatiating objects every time. (Heck, even the ASP.NET runtime creates a new instance of your page object every time in classic ASP.NET - not sure about MVC).
But if your object has non-trivial initialization time (intensive processing in constructor or upon first method call), then you'll probably want to look at two options:
One) Storing the object in the session - be careful here as your object may behave differently depending on the backend session store (memory, sql, etc).
MyHeavyObj obj = (MyHeaveyObj) Session["cachedObj"];
if (obj == null)
{
obj = new MyHeavyObj();
obj.Init();
Session["cachedObj"] = obj;
}
obj.DoSomething();
Two) Writing your own Windows Service that serves up your objects via remoting and takes care of initiatlization internally. The drawback here is you need to make sure your service scales as your traffic grows.
MyHeavyObj obj = GetHeavyObjViaRemoting();
obj.DoSomething();