This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.
When working with an NHibernate session (the ISession instance), any changes you make – saving, updating, deleting entities – are only executed when the session is flushed. When the actual flushing occurs depends on the session’s flush mode (the FlushMode property). This mode can be one of the following:
- Never: changes are never flushed automatically, you must call ISession.Flush() explicitly;
- Commit: changes are sent as soon as the current ITransaction is committed, no need to call Flush();
- Auto: the session is flushed if a query is requested for some entity type and there are dirty local entity instances, no need to call Flush(); this is the default;
- Always: the session is flushed before any query is executed, also no need to call Flush().
What this means is: depending on the current flush mode, your changes may not reach the database at all (if you are using modes Never and forget to call Flush() or Commit and you do not commit your transaction) or you may be sending changes before you actually want to do it (if using Auto and you execute a query over some entity’s type for which you have pending local changes or Always).
So, for speed, choose Never, for better state synchronization, choose Always or Auto and for using transactions, choose Commit. And don’t forget to monitor what’s going on (using log4net, for example) and to code accordingly to your decision.
There may be times when you want a particular setting applied to all controls of a given type, in all pages. Or you want to debug this control, but you don’t have access to it’s source code. Or you want to change its behavior. For that, you can use tag mapping, and I have given an example before.
In a nutshell, ASP.NET lets you change the control that would normally be instantiated by some server tag (like <asp:Image />, <asp:TextBox />, etc) for your own control, which must inherit from the class of the original control. This means that on all places that you have declared, for example, an <asp:TextBox />, instead of the standard TextBox, ASP.NET will instead place an instance of your own class, where you can override methods, set property defaults on its constructor or place breakpoints.
Usage is very simple, just add entries to the tagMapping section:
Remember, MyTextBox must inherit from TextBox, or you will get an exception.
All of the properties that are present on markup will be passed to the new control, skins will also apply. In case you are wondering, this won’t work with web user controls (those that have an .ASCX file).
What happens when the URL that your image is pointing to does not exist or cannot be reached? Well, all browsers I know of resort to displaying something like:
Sometimes, however, we may be able to anticipate that a given image won’t be accessible and instead choose to serve something else. For that, we can rely on the DOM onerror event; in the case of img tags, this event is raised when the target image cannot be displayed. In that situation, we have the opportunity to change its src property to point to a valid, alternative, location.
One control that we use to display images in ASP.NET is the venerable Image. What if we could change this control so that it supports an alternative URL, in case its target image cannot be loaded? It turns out, it is very easy to achieve this! Let’s start with some code:
As you can see, I added an extra FallbackUrl attribute to the control’s declaration. Image won’t mind, because it implements IAttributeAccessor, which, in case you don’t know, allows for having extra attributes, that is, attributes that cannot be mapped to actual properties.
There are two ways to proceed:
This time, I’ll go for option 2. Let’s implement one such control:
Tag mappings, as its name implies, allow mapping one tag to another, that is, effectively replacing all instances of a control declared on markup for another control. This other control must be a class that inherits from the declared one. This is the case in my example. Here’s the way to go:
And that’s it! All Image controls on your site, provided you add them a valid FallbackUrl property, will display an alternative image if the target image cannot be found! Easy, don’t you think?
Next in the series is modules. So, what is a module, and what does it do?
A module is some class that implements IHttpModule. This is a very simple interface, which only defines two methods:
- Dispose: called when the application shuts down.
A module is typically statically registered on the Web.config file, although I have talked in the past on how to register modules dynamically. While a module usually does not actually do anything by itself, it is useful for registering event handlers for ASP.NET application lifetime events, such as Error, BeginRequest, EndRequest and their likes. Please note that there is no event for the Start occurrence (normally handled on the custom Global class on an Application_Start method), you can just use the Init method for that, since it is called upon application startup.
Out of the box ASP.NET includes a number of modules, which you can find on the global Web.config file, located in %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\Config, some of which you are free to disable, that is, remove on you local Web.config file:
As you can see from the above snippet, one such module is PassportAuthentication, implemented by PassportAuthenticationModule, one that is marked as deprecated in current versions of .NET. Now, there are two sections where modules can be registered, one for IIS versions prior to 7, and the other for recent versions. Of course, if you only use one of them, do forget about the other section.
A simple module implementation would be:
This module registers an event handler for the EndRequest event, which, when called, outputs a string to the response. Nothing to be done on disposing, in this case, but a typical use case would be to release any sort of “heavy” module-held resources when the application shuts down. Please be careful to perform operations only when you can, for example, session is only available after the AcquireRequestState event is raised (and, of course, only for handlers implementing IRequiresSessionState), caller identity is only set after the AuthenticateRequest and authorization is only confirmed after AuthorizeRequest.
You should favor writing code that handles an event in a module as opposed to having a similar method on Global.asax.cs because a module is more portable – you can even reuse it between different assemblies.
Once you are finished, you need to register your module on Web.config, to have it being set up automatically. You have to give it a unique name and add an entry like the following:
Next, handlers and routes!