At times it is desirable to create an absolute URL for a HTML element's href or src attribute. I failed to find a shrink wrapped mechanism to generate them in ASP.NET MVC, and some of the methods I found on the web were not quite what I wanted. So I created extension methods for the Uri class, which will generate absolute URLs relative to the current context's Request.Url property.

The class definition follows:

public static class UriHelperExtensions
{
   // Prepend the provided path with the scheme, host, and port of the request.
   public static string FormatAbsoluteUrl(this Uri url, string path)
   {
      return string.Format( 
         "{0}/{1}", url.FormatUrlStart(), path.TrimStart('/') );
   }

   // Generate a string with the scheme, host, and port if not 80.
   public static string FormatUrlStart(this Uri url)
   {
      return string.Format( "{0}://{1}{2}", url.Scheme, 
         url.Host, url.Port == 80 ? string.Empty : ":" + url.Port );
   }
}

The following snippet of code from an ASP.NET MVC Razor view demonstrates how to generate an absolute URL given the relative URL /images/img.jpg.

   <img src="@Request.Url.FormatAbsoluteUrl("/images/img.jpg")" alt="Alt text" />

For my blog, the HTML generated for the img element will be:

   <img src="http://www.nathanfox.net/images/img.jpg" alt="Alt text" />

I hope this helps :-)

Technical ASP.NET .NET ASP.NET MVC January 25, 2012

Rendering a page on my blog requires 12 JavaScript files and 3 CSS files. This is is a lot of HTTP request overhead. I decided to use AjaxMin to combine and minify my JS and CSS files. Now my pages only requires one JS and one CSS file.

AjaxMin can use an XML file to specify which files to minify and combine along with the target output file. The input file for my blog:


<root>
   <output path="..\..\web\site.js">
      <input path="..\..\web\syntax\scripts\shCore.js" />
      <input path="..\..\web\syntax\scripts\shLegacy.js" />
      <input path="..\..\web\syntax\scripts\shBrushCSharp.js" />
      <input path="..\..\web\syntax\scripts\shBrushXml.js" />
      <input path="..\..\web\syntax\scripts\shBrushPlain.js" />
      <input path="..\..\web\syntax\scripts\shBrushVb.js" />
      <input path="..\..\web\syntax\scripts\shBrushPowerShell.js" />
      <input path="..\..\web\scripts\jquery-1.7.1.min.js" />
      <input path="..\..\web\scripts\json2.js" />
      <input path="..\..\web\scripts\jquery.validate.min.js" />
      <input path="..\..\web\scripts\jquery.form.js" />
      <input path="..\..\web\scripts\FoxBlog.js" />
   </output>
   <output path="..\..\web\site.css">
      <input path="..\..\web\syntax\styles\shCore.css" />
      <input path="..\..\web\syntax\styles\shThemeDefault.css" />
      <input path="..\..\web\content\site.css" />
   </output>
</root>

The file name for the XML input file will be passed through the -xml argument to AjaxMin.

I'm running AjaxMin out of a folder off the root of my checkout tree, so the paths to all the files are relative paths that resolve to my web project folder structure. The folder structure of interest is shown below.

Web folder structure for my project using AjaxMin

AjaxMin is run out of the 3rdParty\AjaxMin folder. The input file is also located in the AjaxMin folder. The command to run AjaxMin:

ajaxmin -clobber -xml AjaxMin.xml

After executing AjaxMin, the files site.css and site.js will be created in the Web folder. These are the files that will be referenced in the website code.

AjaxMin can be run as a build event in Visual Studio, although technically it would only be necessary to run it if any of the CSS or JavsScript changes. A build event command for the above project structure:

$(ProjectDir)..\3rdParty\AjaxMin\ajaxmin -clobber -xml $(ProjectDir)..\3rdParty\AjaxMin\AjaxMin.xml

It might be better to set up a external tool in Visual Studio to run AjaxMin, a shortcut, or whatever is most convenient.

Keep in mind, some sort of versioning needs to be done with the CSS and JS files so the browser will download the latest version of the file. I have yet to implement a versioning mechanism for my blog, but I need to get to it at some point. Maybe a blog post about it as well :-)

Technical ASP.NET ASP.NET MVC November 30, 2011

The ClientBuildManager is a .NET BCL class that facilitates compiling ASP.NET markup files outside of IIS. I did run into an issue using this class which others may hit as well.

I compiled some ASP.NET MVC .aspx views and tried to get the type using ClientBuildManager.GetCompiledType, but the GetCompiledType function returned null. Hmm…I could see the compilation was working because the assemblies were seemingly generated correctly.

It ends up that the type would not load because the calling project did not reference all the assemblies needed to load the type. The ClientBuildManager compiles the web components in a separate application domain. When trying to retrieve the type, the assembly is loaded into the calling application domain, and then the type retrieval is attempted. If the type can not load no error is thrown, instead you get a null return value.

So make sure the application using ClientBuildManager references all assemblies referenced by the web application you are compiling.

I hope this saves someone some time. It took a bit of head banging to figure this one out. I had to debug down into System.Web to figure out what was going on :-(

Technical ASP.NET ASP.NET MVC August 6, 2010