Slink Framework - Strongly Typed URLs for ASP.NET

7 minute read,

 image926

image_thumb15_thumb45

I decided it was time to solve a very annoying and time consuming code maintenance/quality problem when working with ASP.NET and Visual Studio, URL verification.  If you’re like me, you’ve probably had your fair share of HTTP 404s and ASP.NET maintenance troubles whenever you renamed a file in your web project and broken URLs in the code-behind pages that contain scattered uses of Response.Redirect() similar to the following:

protected void Page_Load(object sender, EventArgs e)
{
    if ( User.IsInRole( "admin" ) )
    {
        Response.Redirect( "~/Page2.aspx" );
    }

    if( User.IsInRole( "employee" ) )
    {
        Response.Redirect( "~/EmployeePages/ViewCustomers.aspx" );
    }

    if( User.IsInRole("customer") )
    {
        Response.Redirect( "~/CustomerPages/ViewCatalog.aspx" );
    }
}

The site validation in Visual Studio somewhat is limited in its ability to validate URLs.  Visual Studio validates URLs in the HTML markup view, but doesn’t validate your URLs in code-behind pages.  That’s a bummer, because the code above is somewhat common in projects.  Invalid URLs that exist in your code-behind pages are hard to debug and locate… you usually don’t know when you have an invalid URL lurking in your code-behind until you hit the page with your browser.  Most modern refractoring tools today do a good job refactoring code for renamed files; however, since most refactoring tools are searching for strings when renaming an ASPX file, there is a potential for error.  There have been many times when refactoring didn’t help me and only made the problem worse by selecting the ”search string literals” option. Refactorability degrades when you start dealing with different media types in your markup and code-behind pages, such as Images, SWF, CSS, and JavaScript URLs.  Media types like these go unchecked, try refactoring those in your pages!:cry: Personally, I’d love it if there was some kind of strongly typed URL framework.  Fortunately, there has been some work in this area by Fabrice Marguerie and his open source project PageMethods.  In summary, PageMethods was too strict, and didn’t work well for my purposes.  I simply wanted a light-weight and fast URL framework to provide links to pages and media objects that I could use in code-behind pages and HTML markup.  I also wanted to know at compile time the validity of all the URLs in my project.  So, I decided to tackle the problem myself with a small project I created called (Strong Link), aka Slink.

Now, let’s revisit the same maintainability problem above using Slink with strongly typed URLs:

protected void Page_Load( object sender, EventArgs e )

{
    if( User.IsInRole( "admin" ) )
    {
        Response.Redirect( Slinks.Page2.TidleUrl );
    }

    if( User.IsInRole( "employee" ) )
    {
        Response.Redirect( Slinks.EmployeePages.ViewCustomers.TildeUrl );
    }

    if( User.IsInRole( "customer" ) )

    {
        Response.Redirect( Slinks.CustomerPages.ViewCatalog.TildeUrl );
    }       
}

With Slink, not only do you get cleaner code, you get compile time checking for code-behind pages! You can also use type safe links in HTML markup:

<h4>Customer Pages</h4>

<!-- The old way, using relative path -->
<img src="~/Images/CustomerImage.jpg" alt="not strongly typed image" />

<!-- The new Slink type safe way, using img HTML tag -->
<img src='<%# Slinks.Images.JPG.CustomerImage.TildeUrl %>' alt="strongly typed url" runat="server" />

<!-- The new Slink type safe way, using a web control -->
<asp:Image ID="imgControl" runat="server" ImageUrl='<%# Slinks.Images.JPG.CustomerImage.TildeUrl %>' />

Yeah! And the list goes on:

  • Better Maintainable Code
  • Better Cleaner Code
  • Better Readable Code
  • Better Refactorable Code
  • Better Quality Code
  • Support for media types other than ASPX pages
  • Fast code generation
  • Non-intrusive overhead (no need to call any setup methods or expensive runtime checking)
  • Use as-you-go integration (doesn’t require any rewrites of your code to start using Slink)
  • XML configuration based
  • Intellisense for any of your files and media objects!

Now that’s what I’m talking about. So how do you get your hands on all this Slink ASP.NET goodness?  Keep reading…

There are two basic ways to use Slink:

  • You can use Visual Studio and an accompanying CR_Slink Plug-In (via DXCore) to automatically generate a type safe file in your projects App_Code directory.

OR

  • You can use Slink.exe in a build task to generate a strongly typed safe file in your App_Code directory.

Details about how to setup each method is discussed later.  First, there’s some XML configuration you’ll need to perform to tell Slink what to generate.  Here is a sample configuration that you place in your Web.config:

<!-- Web.config -->
<configuration>
  <configSections>
       <section name="Slink" type="Slink.Core.SlinkConfigSection, Slink.Core"/>
  </configSections>

  <Slink>
     <GlobalSettings EngineEnabled="True" RootNamespace="Slinks"/>
     <NamespaceRules>
        <add key="aspxFiles" Extension="*.aspx" UseFolderNamespace="True"/>
        <add key="jpgFiles" Extension="*.jpg" NamespaceOverride="Images.JPG"/>
        <add key="pngFiles" Extension="*.png" NamespaceOverride="Images.PNG"/>
     </NamespaceRules>
  </Slink>

  <!-- Other configuration settings go here -->
</configuration>

Below is a brief explanation of the XML configuration settings…

<section name="Slink" type="Slink.Core.SlinkConfigSection, Slink.Core"/>
  • This section handler needs to be added to the <configSections>. The <section> tag defines the XML node that is to be handled by the SlinkConfigSection on behalf of the .NET configuration framework.
<Slink>
    <GlobalSettings EngineEnabled="True" RootNamespace="Slinks"/>
  • The <GlobalSettings> node has two attributes EngineEnabled and RootNamespace.
    • EngineEnabled - Boolean - This is a project level setting. You may want to disable type safe link code generation at the project level if you are working with multiple Web Projects.  Setting EngineEnabled="False" disables code-generation at the web-project level.
      • RootNamespace - String - Allows you to specify the Namespace for all type safe links.

image_thumb115 

<NamespaceRules>
    <add key="aspxFiles" Extension="*.aspx" UseFolderNamespace="True"/>
    <add key="jpgFiles" Extension="*.jpg" NamespaceOverride="Images.JPG"/>
    <add key="pngFiles" Extension="*.png" NamespaceOverride="Images.PNG"/>
</NamespaceRules>
  • <NamespaceRules> are at the core of Slink.  Namespace rules dictate how type safe code is generated by the Slink Engine.  Namespace rules allow you to define what type of files get type safety.
    • Extension - String - If you wish to have type safe code generated for all ASPX pages, add a namespace rule with the Extension attribute set to “*.aspx”. Including the * (asterisk) is necessary.
      • UseFolderNamespace - Boolean - Uses the file path to generate the sub-namespaces below the root namespace.
      • NamespaceOverride - String - Overrides the UseFolderNamespace attribute and allows you to define your own custom path.  Your custom namespace override is appended to RootNamespace. See the example below for JPG and PNG namespace overrides:

image_thumb15_thumb35

NOTE: If you have multiple files with the same name but different extension, you’ll want to override namespaces to avoid type collision.

Now that we have XML configuration out of the way, I’ll walk you through on how to install Slink on your machine.

image_thumb285

Installing VS.NET Plug-In

  1. Install the DXCore (free) extensibility framework for Visual Studio from Developer Express here.
  2. Download the Slink binaries Slink_bin.zip.
  3. Copy the contents of Slink_bin.zip into your DXCore Plug-In directory
    • Ex: C:\Program Files\Developer Express Inc\DXCore for Visual Studio .NET\2.0\Bin\Plugins
    • Note: All contents of the Slink_bin.zip must be extracted into the plugins directory.
  4. Make sure your XML config section is defined in your Web.config, and start coding away!

Using Slink.exe

image_thumb275

Now, if you’re already using the Visual Studio Plug-In, there’s no need to use the Slink.exe.   But for those of you who don’t have Visual Studio, or are using Visual Studio Express, using Slink.exe is the way to go.

Installing Slink.exe

  1. Download the Slink binaries Slink_bin.zip.
  2. Extract the contents of to the directory of your choice
    • Ex: C:\Tools
  3. Run the following from the command line:
    • C:\Tools> slink.exe /webproject:<PathToWebProject>
    • Replace <PathToWebProject> with the full path to your project.
  4. Be sure to modify your Web.config and your Namespace Rules are set.  Otherwise, the Slink won’t know what to do.

TIP: Unfortunately, Web Projects in Visual Studio are handled differently than ordinary projects.  With web projects, you can’t specify any “Pre-Build” event tasks.  But there’s an easy workaround for this limitation.  If you’re using Visual Studio Express, and want to have your types generated before the build process/verification of your main web project, you can create a standard dummy “Class Library”.  In the pre-build event for your dummy “Class Library” you can setup Slink to execute.  Then, add the dummy “Class Library” to your main web-project.  Now, anytime you build your website, your class library will be built first (and slink will run) before the build / verification process takes place on your main web-project.

That all!  After building web project (if you’re using the VS.NET Slink Plug-In) or when you execute Slink.exe, you should get a file named <WebProject>\App_Code\Slinks.cs that contains your type safe URL generated code.

If you have any questions, comments, or suggestions please feel free to contact me. I hope other developers find the Slink framework useful.

Happy coding!


http://codeplex.com/slink

  • Add support for strongly typed parameter passing/parsing for query string parameters.
  • Create a standalone Slink Plug-In that does not rely on DXCore.
  • Implement more advanced code generation caching.
  • Possibly implement /code generate a helper methods on media types such as “MyImage.GetStream()” that would automatically open and return an IO stream.

Licence

This library and code generator is licensed under the terms and conditions defined in the GNU Public License. You are free to use it for non-commercial purposes. If you are going to use any part of it in a commercial application, contact me and we can work something out.  You may use the code generated output of Slink in both commercial and non-commercial applications.

Special Thanks

Special thanks and acknowledgments go out to Philip Laureano for building his open source TaHoGen code template generator.  Without it, Slinks would not exist.

Comments

Brian Chavez

Hi Paul, I haven’t tried it with VS 2008 beta2 yet. I don’t have it installed on any of my dev machines. The VS.NET Plug-In might not work, but the Slink.exe should work no matter what VS.NET version you’re using, as far as I know.

If it works in VS.NET 2008, let me know and I’ll update this article! :)

Tommy

What about Querystring and Postdata support? I was thinking about ditching PageMethods completely for this utility, but I am also using PageMethods to ensure querystring data are valid.

Brian

Hi Tommy,

I’m sorry, QueryString and PostData isn’t supported yet under Slink. If you have a good architectual way to build it into Slink, let me know!

Thanks,
Brian

Philip Laureano

Thanks, Brian!

Wow, I can’t believe someone’s still using my old framework!

Tt’s always good to know that some of my old work is out there helping someone else.

Btw, if you’re interested, I’ve got the source code for TaHoGen v5 lying around somewhere for you to use. I’m probably going to put it under LGPL since I don’t have much commercial use for it, so if you want to use it, just let me know if your interested.

Regards,

Philip Laureano

>Special Thanks

>Special thanks and acknowledgements go >out to Philip Laureano for building his >open source TaHoGen code template >generator. Without it, Slinks would not >exist.

Leave a comment

Your email address will not be published. Required fields are marked *

Loading...