Click here to Skip to main content
15,890,186 members
Articles / Web Development / ASP.NET

Strongly typed page references in ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.60/5 (21 votes)
31 Jul 2007CPOL2 min read 47.6K   28   17
How to create strongly-typed references to pages within your ASP.NET solution.

Introduction

Constructing the URL to a page within your solution is typically a messy task. Wouldn't it be nice if you could just say something like:

C#
Redirect(new PrintItemPage(item, itemFormat))

That, of course, will not work.

So, instead of some nice, clean, strongly typed solution like that, we see people embedding references like "~/Print/Printitem.aspx" all over their solution. And, if that page needs parameters, they may well use string concatenation to construct the URL, maybe something like:

C#
string url = "~/Print/Printitem.aspx?id=" + item.Id + "&format=" + itemFormat;

The smarter developer will have realized that it's better to define the basic URL string in a single location in the solution, and will have a constant string for that:

C#
// In the code behind for Printitem.aspx in the /Print directory
public const string baseUrl = "~/Print/Printitem.aspx?id={0}&format={1}";

But typically, the parameters for that page are still added in a weakly typed manner to the URL, something like:

C#
string url = string.Format(Printitem.baseUrl, item1.id, item2.format)

Background

Code such as that shown in the introduction has several issues:

  1. References to ~/Print/Printitem.aspx are often scattered throughout the solution, making it hard to move a page to a different folder or to rename it.
  2. The parameters for the page are weakly typed, allowing run-time errors when someone accidentally links to that page, passing the ID for a Foo instead of an Item.
  3. It is hard to discover (using the IDE) what the various parameter combinations are that can be used when referring to a different page in the solution.

Using the code

The solution to these issues is to create a strongly-typed static method on each of your page classes that returns a fully formed URL for that page. If there is more than one way to call the page, then provide multiple such static methods on your page class.

C#
/// <summary>
/// Construct a URL to self with an Item and an ItemFormat
/// </summary>
public static string UrlToSelf(Item item, Itemformat itemFormat)
{
    return string.Format("~/print/printitem.aspx?id={0}&format={1}", 
                         item.id, itemFormat.ToString());
}

/// <summary>
/// Construct a URL to self with just an Item (will use the default ItemFormat)
/// </summary>
public static string UrlToSelf(Item item)
{
    return UrlToSelf(item, ItemFormat.Default);
}

With these static methods in place, you can now discover (using the IDE) how to call the PrintItem page. Intellisense will show you that there are two calls you can make and that you must pass in an Item object.

Screenshot - Article.gif

It's now impossible for you to link or redirect over to the PrintItem page passing it anything but the object type it expects.

Points of interest

Duplicate code is always a bad idea: it leads to code bloat; it causes bugs to appear in some places, but not others; bugs 'fixed' mysteriously reappear in other places because the developer didn't go find all copies of that code when he or she fixed a bug that had been found in one of them.

"One-fact, one-place" is a great mantra not just for database developers, everyone should aim for it. If you are ever tempted to use "cut-and-paste coding" because it's 'quicker', just remember that 2x the code will produce 2x as many bugs and will be 2x as hard to maintain. It is always better to avoid duplication and to spend time creating a reusable method that puts "one fact" in "one place". Every sprint cycle should include time for this kind of refactoring to ensure that your solution stays clean and maintainable.

Related article

See also ... another article on how to do the same for Web User Controls.

History

  • July 2007, First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I have been writing code and managing teams of developers for more years than I care to remember.

Comments and Discussions

 
GeneralMy vote of 2 Pin
Paulo Zemek15-Apr-09 2:29
mvaPaulo Zemek15-Apr-09 2:29 
GeneralRe: Auto-discovery of path Pin
HightechRider20-Apr-09 11:25
HightechRider20-Apr-09 11:25 
Questionforcing implementation Pin
jimischacht28-Nov-07 5:06
jimischacht28-Nov-07 5:06 
AnswerRe: forcing implementation Pin
HightechRider28-Nov-07 9:09
HightechRider28-Nov-07 9:09 
GeneralIt's great Pin
LucianoCN9-Aug-07 19:58
LucianoCN9-Aug-07 19:58 
GeneralGlad to see my idea is being publicized. Pin
Peter Lanoie7-Aug-07 4:39
Peter Lanoie7-Aug-07 4:39 
GeneralBrilliant! Pin
Mark II6-Aug-07 22:58
Mark II6-Aug-07 22:58 
GeneralNice Pin
Howard Richards6-Aug-07 21:45
Howard Richards6-Aug-07 21:45 
GeneralPoints of Interest, Yeah duh Pin
Stanley Gillmer6-Aug-07 19:18
Stanley Gillmer6-Aug-07 19:18 
GeneralKeep up the good work Pin
GreatPokerHands5-Aug-07 20:16
GreatPokerHands5-Aug-07 20:16 
GeneralNice alternative Pin
Sergey Rybalkin1-Aug-07 7:50
Sergey Rybalkin1-Aug-07 7:50 
GeneralRe: Nice alternative Pin
JohnDeHope32-Aug-07 6:48
JohnDeHope32-Aug-07 6:48 
GeneralGreat Idea Pin
JohnDeHope31-Aug-07 6:20
JohnDeHope31-Aug-07 6:20 
I really liked your idea, sir! I like things that are correct at compile-time, it gives me a warm and fuzzy feeling. My only beef is that this ties a page directly to the implementation of the pages it calls. I wonder if an interface and static utility class named (example) IPageNavigator and PageNavigator, which had methods like NavigateToX, NaviagteToY, etc. would be nicer. This way the pages would only be tied to an interface, not a specific class. And the information about how to turn a page navigation into a URL would all be centrally located in a single class. Finally, when running unit tests, you could swap out the real PageNavigator for a stub entry that would just acknowledge a navigation request, and not actually do it.

But anyway... this really is an ingenious solution that never occured to me in years of web programming. Heck we could have been doing this same thing back in the ASP 3.0 days. It would not have been verified at compile-time, but the rest of the coolness would still be intact.

You deserve a medal.

http://www.ronpaul2008.com/
GeneralSometimes the simplest solutions are the best Pin
Jamie Nordmeyer1-Aug-07 4:19
Jamie Nordmeyer1-Aug-07 4:19 
GeneralGreat Idea! Pin
merlin9811-Aug-07 4:05
professionalmerlin9811-Aug-07 4:05 
GeneralRe: Great Idea! - interface IRedirect Pin
HightechRider1-Aug-07 7:06
HightechRider1-Aug-07 7:06 
GeneralRe: Great Idea! - interface IRedirect Pin
merlin9811-Aug-07 7:40
professionalmerlin9811-Aug-07 7:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.