Most URL rewriters out there only let you rewrite requested URL's to internal URL's. In practice, you often see people create/generate friendly URL's and then create mappings for those friendly URL's to internal URL's. Whenever you would decide to change your friendly URL's, you have a problem. You have to change the mappings AND the created/generated URL's.

To overcome this problem, I put together a 2-way URL rewriter. It lets you define mappings from a friendly url to the real url, and vice versa. The default web config rule provider lets you define the mappings as follows:

XML:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 

<configuration>
  <configSections>
   <section name="rewriter" type="Wilco.Configuration.ProviderSectionHandler, Wilco.Configuration" />
  </configSections>

  <rewriter>
    <provider type="Wilco.Web.RewriteEngine.Providers.WebConfigRuleProvider, Wilco.Web.RewriteEngine">
      <rules>
        <rule>
          <!-- /blah.aspx - /default.aspx -->
          <inbound pattern="~/blah.aspx" replacement="~/default.aspx" />
          <outbound pattern="~/default.aspx" replacement="~/blah.aspx" />
        </rule>
        <rule>
          <!-- /news/123 - /news.aspx?newsid=123 -->
          <inbound pattern="~/news/(\d+)$" replacement="~/news.aspx?newsid=$1" />
          <outbound pattern="~/news.aspx\?newsid=(\d+)$" replacement="~/news/$1" />
        </rule>
      </rules>
    </provider>
  </rewriter>

  <httpModules>
    <add name="Rewriter" type="Wilco.Web.RewriteEngine.Rewriter, Wilco.Web.RewriteEngine" />
  </httpModules>
</configuration>

The rewriter comes with an HttpModule which takes care incoming URL's. Internally it relies on the helper method 'string UrlUtility.ConvertToRealUrl(string friendlyUrl)'. This helper class also contains a method 'string UrlUtility.ConvertToFriendlyUrl(string realUrl)', which does the obvious.

Custom providers can be implemented, by either inheriting from the web config rule provider or implementing IRuleProvider. You can download the binaries and source for free.

License:
This project is released under Ms-PL. Please contact me directly for questions or exceptions.

Update:
Please have a look at my HtmlFormEx implementation which should be used together with this component to solve an issue with postbacks.

Great idea.

It would be even better if you didn't have to write both the inbound and outbound tags unless explicitly required. Your first example is of the form:
XML:
1 
2 
3 

<!-- A - B -->
        <inbound pattern="A" replacement="B" />
        <outbound pattern="B" replacement="A" />


In this case something like this would be half the work to set up
XML:
1 
2 

<!-- A - B -->
        <rewrite inbound="A" outbound="B" />


Of course the second example is more tricky, and I guess this is the more useful of the two. If you could come up with some syntactic sugar to make (\d+)$ and $1 equivalent (since they're merely transposed in inbound and outbound) then you'd REALLY be onto something. Of course that means you couldn't simply rely on RegEx, but...

I did consider it for a second, but there were a few reasons why I didn't go that way:
1. Whatever I would come up with, it wouldn't be anywhere near as flexible as regex (although you arguably need the flexibility, oh well)
2. Sometimes you may want to map multiple paths to a single location (inbound or outbound). While this could be allowed for by using different order, I think the current model is more explicit/readable.

I may change my mind though, and see if I could come up with something that lets you define a single mapping that works both ways.
Your message will be encoded/formatted when it is displayed. If you want to post code, please put the code inside [code=X][/code] tags, where X is the language of your code (C#, ASPX, SQL, etc).
Name:
Email:
(will be encoded using JavaScript to keep it functional and prevent it from being picked up by spammers)
Url:
 
Message:
3 + 3 =