![]() |
Web Development »
ASP.NET »
General
Intermediate
ASP.NET 1.1 Web Application Compilation and Pre-compilation - EnhancedBy Jecho JekovEnhancements to how to pre-compile or compile .aspx and .ascx files of C# or VB ASP.NET 1.1 web application; includes full source code, compilation library, runtime library and demo project. |
C#, XML, Windows, .NET 1.1, ASP.NET, VS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Please see the original article first: ASP.NET 1.1 Web Application Compilation and Pre-compilation.
The idea given by Peter Tewkesbury:
The requirement to change the IIS configuration for embedded resources troubles me. I look after a number of websites, which are hosted for me and I do not have access to the IIS settings. On my websites, I have a handler that creates thumbnail images from the full image. The code for this is not important.
This is the idea that I have had:
Then you don't need to change any IIS settings - A big plus for everyone who has hosted websites.
This article is concerned with the implementation of this idea and its usage in your application. The source code is also rewritten and has a better design so that you can use this instead of the one in the old article.
As the previous article describes it is possible to embed any external file that your application requires (e.g. .gif, .css, etc.) in an assembly and requests to such files are to be served by your application instead of IIS. In order that IIS forwards requests to such files (e.g. "/MyApp/Css/Global.css") to ASP.NET runtime (and your application) the file name extensions should be mapped at IIS to aspnet_isapi.dll. Additionally, the extensions should be mapped to System.Web.IHttpHander implementator (e.g. WebApp.Web.Compilation.Runtime.ResourceFileHandler ) that will load the file content from the assembly and return it as a response to the requests. This mapping is done through web.config. If, for example, you want your application to serve requests to .css and .gif files you need to manually (or by using script) map these extensions at IIS to aspnet_isapi.dll and add the following lines in your web.config:
<system.web>
<httpHandlers>
<add verb="*" path="*.css"
type="WebApp.Web.Compilation.Runtime.ResourceFileHandler,
WebApp.Web.Compilation.Runtime" />
<add verb="*" path="*.gif"
type="WebApp.Web.Compilation.Runtime.ResourceFileHandler,
WebApp.Web.Compilation.Runtime" />
</httpHandlers>
</system.web>
However, changing the IIS settings make the deployment of your application more difficult and it may not be always possible to do that. The solution is to make requests to such files to appear, as they are requests to files whose extensions are already registered at IIS: for example .aspx or .asmx. This may be done by substituting links to such files (e.g. "/MyApp/Css/Global.css") by links of type "handler?p=file_id" (e.g. "FH.aspx?p=Css/Global.css"). "handler" should have a path whose extension is already mapped at IIS to aspnet_isapi.dll (.aspx, .asmx, etc.) and file_id should be string by which the Win32 resource that corresponds to the file can be loaded from the assembly. As a result, no IIS settings need be changed but the following lines should be presented in your web.config:
<system.web>
<httpHandlers>
<add verb="*" path="FH.aspx"
type="WebApp.Web.Compilation.Runtime.ResourceFileHandler,
WebApp.Web.Compilation.Runtime" />
</httpHandlers>
</system.web>
A solution should target the following issues:
Embedding files to assembly is done by the WebApp.Web.Compilation.ResourceBuilder type. It enables building of Win32 Resource (.res) file which is to be included in compilation. The type provides two kinds of methods:
If a resource is named then later on it can be accessed only by its name by the WebApp.Web.Compilation.Runtime.ResourceManager type. The name of a resource is of System.String type and differs from the Win32 resource name, which is of type System.UInt16. To enable support of string names of resources a common index is built and saved as an additional resource. Note: Although a Win32 resource name and/or type can be a string this is not implemented.
The main issue is how to choose the name for the resource of a file being added:
This solution provides two WebApp.Web.Compilation.Runtime.IResourceNameProvider implementations that are responsible to provide names for files being added as resources:
WebApp.Web.Compilation.Runtime.RelativePathNameProvider
WebApp.Web.Compilation.Runtime.EncodedNameProvider The RelativePathNameProvider derives the name of the resource from the relative path to the file based on the application's root directory. That is, if the application is located in C:\MyApp and the file is C:\MyApp\Css\Global.css the name would be Css/Global.css.
EncodedNameProvider does the same as the RelativePathNameProvider but applies base64 encoding on the relative path.
The following files that may contain links to other embedded files should be the target:
The following strategy is used:
System.Web.HttpRequest.MapPath(string,string,bool) method.
@"('|""|\()(?<1>(\w|[.% \/~])*?\.(htm|html|js|...))('|""|\))"). This allows links to be located regardless of the name of the tag and attribute as they are specified in JavaScript/CSS code. For more information, see the WebApp.Web.Compilation.FileReferencesFixer type. Links in such files are substituted prior to the files to be parsed by the System.Web.UI.TemplateParser descendants (i.e. a file's content is read, altered and then passed to the parser). Because of the way links are searched links specified within tags that has runat="server" attribute specified are also handled (e.g. <asp:image ImageUrl="~/Images/Logo.gif" runat="server"> will become <asp:image ImageUrl="FH.aspx?p=Images/Logo.gif" runat="server">).
Note: Only links that reside within .aspx and .asxc files will be substituted. Any links in code-behind should be handled manually by redesigning the code.
Links in such files are substituted prior to adding their content to Win32 resource file (i.e. a file is read, altered and then appended to the resource file). That means only the files that are embedded itself will be processed. Links in files that are not specified to be embedded will not be fixed.
Generally, there are two types of handler names to choose from: relative to the current virtual path (e.g. "FH.aspx") and relative to the web site root (e.g. "/FH.aspx", "/MyApp/FH.aspx"). The differences are:
<link href="FH.aspx?p=Css/Global.css" rel="stylesheet"> and /SubDir/WebForm1.aspx that contains <link href="FH.aspx?p=Css/Global.css" rel="stylesheet"> a browser will see links to two different files: "/FH.aspx?p= Css/Global.css" and "/SubDir/FH.aspx?p= Css/Global.css" and will request "Css/Global.css" twice (note that "Css/Global.css" is not the relative path to a file but the name of a resource). Because of that links in files that reside in subdirectories are adjusted by adding number of "../" strings in front of the handler's name: e.g. the link in /SubDir/WebForm1.aspx would become "../FH.aspx?p=Css/Global.css". That will cause a browser to request "Css/Global.css" only once. Otherwise if you specify "/FH.aspx?p=..." or "/MyApp/FH.aspx?p=..." as a handler name all links to the same file will be the same (e.g. "/MyApp/FH.aspx?p=Css/Global.css").
If you need to generate links in your code-behind you can use the System.Web.UI.Control.ResolveUrl method (e.g. ResolveUrl( "~/FH.aspx?p=..." )).
At runtime, requests are served by the WebApp.Web.Compilation.Runtime.ResourceFileHandler type. All you need to do is to map the name of the handler to this type in your web.config:
<system.web>
<httpHandlers>
<add verb="*" path="FH.aspx"
type="WebApp.Web.Compilation.Runtime.ResourceFileHandler,
WebApp.Web.Compilation.Runtime" />
</httpHandlers>
</system.web>
Note that the value of the path attribute does not include directory information (e.g. "/FH.aspx", "/MyApp/FH.aspx"). That will cause ASP.NET runtime to forward all requests made to "FH.aspx" anywhere within the application (e.g. "/FH.aspx", "/MyApp/FH.aspx", "/MyApp/SubDir/FH.aspx") to the WebApp.Web.Compilation.Runtime.ResourceFileHandler type.
Additionally, you will need to specify the type of the resource name provider (WebApp.Web.Compilation.Runtime.IResourceNameProvider descendant) in the WebApp.Web.Compilation.Runtime.ResourceFileManager configuration section:
<WebApp.Web.Compilation.Runtime.ResourceFileManager>
<add key="ResourceNameProvider"
value="WebApp.Web.Compilation.Runtime.RelativePathNameProvider"/>
</WebApp.Web.Compilation.Runtime.ResourceFileManager>
or
<WebApp.Web.Compilation.Runtime.ResourceFileManager>
<add key="ResourceNameProvider"
value="WebApp.Web.Compilation.Runtime.EncodedNameProvider" />
</WebApp.Web.Compilation.Runtime.ResourceFileManager>
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 5 Sep 2005 Editor: Rinish Biju |
Copyright 2005 by Jecho Jekov Everything else Copyright © CodeProject, 1999-2009 Web20 | Advertise on the Code Project |