Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Slink Framework - Strongly Typed URLs for ASP.NET

0.00/5 (No votes)
4 Sep 2007 1  
Slink is a code generating Framework that generates type safe URLs for ASP.NET. With Slink URLs, you increase code quality, increase maintainability, and get compile time checking of your URLs in all your ASPX pages (code-behind and non-codebehind).
Screenshot - namespaceview.gif Screenshot - rootnamespace.gif

Introduction

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 refactoring 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! Personally, I'd love it if there was some kind of strongly typed URL Framework.

Existing Work, PageMethods

Fortunately, there has been some work in this area by Fabrice Marguerie and his open source project PageMethods.

After playing around with PageMethods, I quickly found:

  • PageMethods doesn't generate URLs for pages that do not have the [PageMethod] attribute at the time of this writing.
  • PageMethods doesn't generate URLs for media types other than ASPX pages. You can't use PageMethods URLs for JavaScript, CSS, SWF or other images.
  • PageMethods is a bit slow. PageMethods added about 5 seconds to my build time with a project that had about 5 pages.
  • PageMethods uses BasePage and Invoke(this) in PageLoad. Although, not required, it adds to your page hierarchy.

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.

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...

Getting Started with Slink

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" 
            TypesafeGeneratedFileTarget="App_Code\Slinks.cs"/>
        <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.

      Screenshot - rootnamespace.gif

    • TypesafeGeneratedFileTarget - String - Allows you to specify the output file where the type safe code should be generated.
NOTE: The Web.config in this example uses the "Web Site Project" model in VS.NET 2005. If you are using the "Web Application Project" model in Visual Studio, you must remove the App_Code from the TypesafeGeneratedFileTarget, place it somewhere other than App_Code. Read step 4 here to understand why you should not put code in App_Code for "Web Application Projects". For more information on the differences between "Web Applications Projects" and "Web Site Projects", click here.
<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:

Screenshot - namespaceview.gif

NOTE: If you have multiple files with the same name but a 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.

Using Visual Studio Slink Plug-In

Screenshot - slinkplugin2.gif

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
    • E.g. 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. Register the code smith parser COM component that comes with the binary package by running the InstallSlink.bat
  5. Make sure your XML config section is defined in your Web.config, and start coding away!

Using Slink.exe

Screenshot - slinkplugin.gif

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 to the directory of your choice
    • E.g. C:\Tools\Slink
  3. Register the code smith parser COM component that comes with the binary package by running the InstallSlink.bat
  4. Run the following from the command line:
    • C:\Tools> slink.exe /webproject:<PathToWebProject>
    • Replace <PathToWebProject> with the full path to your project
  5. Be sure to modify your Web.config and your Namespace rules are set. Otherwise, the Slink won't know what to do.

TIP: Unfortunately, the "Web Site Project" model in Visual Studio are handled differently than ordinary projects. With "Web Site 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 "Web Site Project" model and you want to use the Slink.exe method for generating your type safe file, all you need to do is create a standard dummy "Class Library". Then add a pre-build task for your dummy "Class Library" and setup Slink to execute. Once you add the dummy "Class Library" to your main web-project, your dummy "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 the 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!

Also, one last note, please use the latest binaries at CodePlex! The binaries here on Code Project may be outdated.

Slink CodePlex Project

See Brian Chavez's post on Slink.

Thoughts & Future Improvements to 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 method 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 acknowledgements go out to Philip Laureano for building his open source TaHoGen code template generator. Without it, Slinks would not exist.

History

  • Version 0.7.0.2 posted - Fixed COM Init Error, added support for Web App Projects in plug-in
  • Version 0.7.0.1 posted - Bug fix in code generator, cleaned up article formatting
  • Version 0.7.0.0 posted - Initial article, first draft

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here