Fundamentals of Themelia - PassThrough Handling
Tuesday, June 24, 2008
This documentation has been updated for Themelia Framework 2.0 Beta 4.
One very important thing that you have be me aware of is Themelia's pass through handler. This is a special handler isn't really a handler at all, but is rather used to signal to Themelia not to set any HTTP handler at all, but to pass the request back to IIS for it to decide the fate of the route. Registering a path to this handler is the same as registering a path to any other handler as the following example will demonstrate:
<themelia.web> <webDomains defaultTarget="/Page_/Photo/Gallery.aspx"> <add> <handlers> <add matchType="pathStartsWith" name="PassThrough" text="/document/pdf/" /> <add matchType="pathStartsWith" name="PassThrough" text="/home/picture/" /> </handlers> </add> </webDomains> </themelia.web>
In this situation, when anyone accesses http://www.yourdomain.com/document/pdf/ or http://www.yourdomain.com/home/picture/, Themelia won't set any handler at all, but will just let IIS handle it, which would normally means that you probably have physical folders or IIS virtual folders set for those paths.
ForceUse
No, this has nothing to do with Jedi mind tricks. The ForceUse pass through handler technique is the most powerful way to over ride Themelia routing. While setting a simple pattern matching as seen in the above example may be enough for most of your needs, using the ForceUse technique is much more powerful. This involves simply setting the PassThroughHttpHandler.ForceUse property to true.
Where has registering the pass through handler will continue the Themelia pipeline allowing the mid and post processors to reset the handler, using the ForceUse property will stop the Themelia pipeline immediately after preprocessing ends. Therefore, there will be absolutely no chance of the route being changed. This logically means that the handlers registered as pass through in the above example, could actually be overridden to use a different handler. For example, Themelia internally sets robots.txt, favicon.ico and WebResource.axd to use the "passthrough" handler. However, if you want to have custom logic with a slick handler for any of these, then go ahead and create a mid processor or, more likely, as a post processor to override this.
Now, while while you may alter those three registrations as you see fit, Themelia has two reserved folders that you are absolutely no allowed to alter. These are the /Resource_/ and /Service_/ folders. These two folders will always use the pass through handler as they, in an internal preprocessor, have set PassThroughHttpHandler.ForceUse to true. These folders are reserved to encourage a level of structure in web sites. It's as bad of an idea to put files in root of your website as it in to put files in on the root of your system hard drive. This is what folders are for.
Therefore, the /Service_/ folder could contain WCF services (i.e. svc files) and the /Resource_/ folder is where you could store images, styles, XAML documents, scripts, and other client-side resources. In fact, any one of my web sites have the following sections:
/Resource_/Code/ /Resource_/Image/ /Resource_/Lib/ /Resource_/Media/ /Resource_/Style/ /Resource_/Xaml/
If you don't want to use these folders, you don't have to. It's not like Themelia creates the folders for you. They are simply reserves as pass through. If you want to have your own Style, Image, or Xaml folders, just setup a simple pass through handler or, to really make a point, create a preprocessor that does custom pattern matching (the Themelia.Web.Http class will help), and set the PassThroughHttpHandler.ForceUse property to true.
Initialization Parameters (Advanced)
Now, if you would like to do use the more hardcore method of the ForceUse, but don't want to create your own preprocessors, you have another option in Themelia's PassThroughPreProcessor. This preprocessor does nothing more take your requests for patterns to be set to ForceUse. So, if you have a bunch of areas you want to force to be passed to IIS, skipping the bulk of the Themelia pipeline, you may use this preprocessor.
To use this preprocessor, you don't actually do anything in code. You actually use Themelia initialization parameters. This essentially means that Themelia allows you to do inline pass through registrations. Here's an example:
<themelia.web> <webDomains defaultTarget="/Page_/Photo/Gallery.aspx"> <add> <preProcessors> <add type="PassThrough"> <parameters> <add name="pdf" value="pathStartsWith,/document/pdf/" /> <add name="photos" value="pathStartsWith,/home/picture/" /> </parameters> </add> </preProcessors> </add> </webDomains> </themelia.web>
With initialization parameters, you can initialize certain (or custom) aspects of your system in configuration. In this case, you are setting up a hardcore directive forcing two patterns to be passed to IIS.
A pass through initialization parameter consists of two parts: a name of your own choosing and a value consisting of the match type, a comma, and the path to match. If no match type is specified as in the following example, "contains" is used by default:
<themelia.web> <webDomains defaultTarget="/Page_/Sales/Report.aspx"> <add> <preProcessors> <add type="PassThrough"> <parameters> <add name="excel" value="/document/xls/" /> </parameters> </add> </preProcessors> </add> </webDomains> </themelia.web>
Note that the types here are the same as used with HTTP handler registration: "startsWith, "endsWith", "contains", "pathStartsWith", "pathContains", "pathEquals", "webDomainPathEquals", and "webDomainPathStartsWith". The example above with this explanation should lead you down the right path.
If you are activating the PassThroughPreProcessor via a Themelia web component, then just set the initialization parameter using the following programmatic syntax:
public class SecurityComponent : Themelia.Web.Routing.ComponentBase { //- @Register -// public override void Register(PreProcessorDataList preProcessorDataList, ProcessorFactoryDataList processorFactoryDataList, HandlerFactoryDataList handlerFactoryDataList, InjectionProcessorDataList injectionProcessorDataList, MidProcessorDataList midProcessorDataList, FallThroughProcessorDataList fallThroughProcessorDataList, PostProcessorDataList postProcessorDataList, PostStateProcessorDataList postStateProcessorDataList, ErrorProcessorDataList errorProcessorDataList) { preProcessorDataList.Add(new PreProcessorData { ProcessorType = "PassThrough", ParameterArray = new Object[] { "pathStartsWith,/document/pdf/", "pathStartsWith,/home/picture/" } }); } }




