• Skip to main content
  • Skip to primary sidebar
  • Skip to secondary sidebar
  • Skip to footer

Coding Still

  • Home
  • About

URL rewriting in an ASP.NET application

October 7, 2014 By _tasos 1 Comment

When ASP.NET 4.0 was released, a really cool feature, routing, was available in both ASP.NET MVC and ASP.NET Web Forms. But there are scenarios that cannot be answered with routing and we need to perform URL rewriting.

Until 3.5 all extensionless request were not processed by the ASP.NET engine and you needed IIS URL rewriting to implement the desired functionality. But with 4.0 (and IIS 7.0 +) and later all requests are processed by ASP.NET and that means we can implement any scenario via code.

To implement URL rewriting you need to make the following 2 steps

1. Apply the URL rewriting

You add at the Global.asax the following function.

void Application_BeginRequest(object sender, EventArgs e)
{
    // Some variables that can be useful, one could also use Request.Url.Segments
    // Server.UrlDecode can be useful if non-ASCII characters are in the URL
    string FullOriginalPath = Server.UrlDecode(Request.Url.ToString());
    string AbsoluteOriginalPath = Server.UrlDecode(Request.Url.AbsolutePath());
 
    string RewritePath = "";
 
    // Here you apply your business logic
    // and decide what the target url will be
 
    // If a rewriting rule applied
    if (RewritePath != "") {
        // Adding all query string items to the new URL
        for (int I = 0; I <= Request.QueryString.Count - 1; I++)
        {
            RewritePath = RewritePath + "&" + Request.QueryString.Keys[I] + "=" + Request.QueryString[I];
        }
        // Apply the URL rewriting
        Context.RewritePath(RewritePath);
    }
}

The main concept here is that we read the original URL and depending our needs we can rewrite it to another URL. We can build the new URL in the RewritePath variable and then use the Context.RewritePath(RewritePath); method to apply the rewriting. For example we have the original URL /contact and we can rewrite it to ~/default.aspx?page=contact (or ~/default.aspx?pageid=4 if page with title ‘Contact’ has the id 4 in our database)

Here it is important to remember that you need to add all the query string items manually in order to pass them to your pages.

Also, inside your code the Request.Url will know the rewritten URL, not the original.

So far this approach works but it has one main issue. When there is a PostBack the URL changes to the one you have set in the Context.RewritePath(…).

2. Avoiding PostBack issue

To avoid this issue you need to add to your projects two ASP.NET folders

  1. App_Browsers
  2. App_Code

In the App_Code folder you create a file FormRewriter.cs and add the following code (In my demo the root namespace is WebFormsRewriting). If you are working with VB.NET, the file name should be FormRewriter.vb. If you have trouble converting the code, feel free to ask in a comment and I will post it.

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.UI;
 
namespace WebFormsRewriting
{
    public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter
    {
        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            base.Render(new RewriteFormHtmlTextWriter(writer));
        }
    }
 
    public class RewriteFormHtmlTextWriter : System.Web.UI.HtmlTextWriter
    {
        public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
            : base(writer)
        {
            this.InnerWriter = writer.InnerWriter;
        }
 
        public RewriteFormHtmlTextWriter(System.IO.TextWriter writer)
            : base(writer)
        {
            base.InnerWriter = writer;
        }
 
        public override void WriteAttribute(string name, string value, bool fEncode)
        {
            // If the attribute we are writing is the "action" attribute, and we are not on a sub-control, 
            // then replace the value to write with the raw URL of the request - which ensures that we'll
            // preserve the PathInfo value on postback scenarios
            if ((name == "action"))
            {
                HttpContext Context = default(HttpContext);
                Context = HttpContext.Current;
 
                if (Context.Items["ActionAlreadyWritten"] == null)
                {
                    // Because we are using the UrlRewriting.net HttpModule, we will use the 
                    // Request.RawUrl property within ASP.NET to retrieve the origional URL
                    // before it was re-written.  You'll want to change the line of code below
                    // if you use a different URL rewriting implementation.
                    value = Context.Request.RawUrl;
 
                    // Indicate that we've already rewritten the <form>'s action attribute to prevent
                    // us from rewriting a sub-control under the <form> control
                    Context.Items["ActionAlreadyWritten"] = true;
                }
            }
            base.WriteAttribute(name, value, fEncode);
        }
    }
}

In the App_Browsers folder you create a file Form.browser and add the following snippet. Note here to put the class name of the Adapter with its namespace.

<browsers>
    <browser refID="Default">
        <controlAdapters>
            <adapter controlType="System.Web.UI.HtmlControls.HtmlForm"
                     adapterType="WebFormsRewriting.FormRewriterControlAdapter" />
        </controlAdapters>
    </browser>
</browsers>

And that’s it. Adding those two files will handle the PostBack issue. If you put the FormRewriter.cs outside the App_Code folder it will not work. Also those two folders must be uploaded to the production server.

Related Articles

  • Tip/Trick: Url Rewriting with ASP.NET
  • Url rewriting in IIS7

Filed Under: ASP.NET Tagged With: ASP.NET Web Forms, Url rewriting

Reader Interactions

Comments

  1. JG says

    March 22, 2018 at 00:35

    Exactly what I needed… I have been wrestling with this postback issue for a while! Shocked that nobody else has commented on how useful this is…

    Reply

Leave a Reply to JG Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Categories

  • .NET Development
  • ASP.NET
  • Databases
  • Fun
  • IIS
  • JavaScript
  • Web Development

Tags

.NET Core Android ANTLR ASP.NET Ajax ASP.NET Core ASP.NET MVC ASP.NET Web Forms AWS Bouncy Castle Chartjs cli Client info detection Comic Continuous integration CSS Data backup Date handling Firebase Firefox addons Github HigLabo HTML5 Image manipulation jQuery JWT MySQL Nodejs Nuget OAuth Objectionjs OOP openssl Oracle ORM PHP Regular expressions SEO Social media SQL SQL Server UI/UX Url rewriting Videos Visual Studio Web design

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Secondary Sidebar

Archives

  • July 2020
  • March 2020
  • August 2019
  • December 2018
  • November 2018
  • February 2018
  • August 2016
  • June 2016
  • May 2016
  • February 2016
  • January 2016
  • August 2015
  • July 2015
  • October 2014
  • July 2014
  • November 2013
  • April 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • May 2012
  • February 2012
  • December 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010

Footer

Recent Posts

  • Anatomy of an Objection.js model
  • Check your RSA private and public keys
  • Round functions on the Nth digit
  • Send FCM Notifications in C#
  • Jwt Manager
  • Things around the web #5
  • Query JSON data as relational in MySQL
  • Create and sign JWT token with RS256 using the private key
  • Drop all database objects in Oracle
  • Create and deploy a Nuget package

Latest tweets

  • Geekiness Intensifies.. NASA used Three.js to render a real-time simulation of this week's NASA rover landing on M… https://t.co/orgkXnYj9O February 19, 2021 18:12
  • Things I Wished More Developers Knew About Databases https://t.co/h4gfq6NJgo #softwaredevelopment #databases May 3, 2020 12:52
  • How a Few Lines of Code Broke Lots of Packages https://t.co/p7ZSiLY5ca #javascript May 3, 2020 12:48
  • Can someone steal my IP address and use it as their own? https://t.co/HoQ7Z3BG69 January 24, 2020 13:27
  • Organizational complexity is the best predictor of bugs in a software module https://t.co/aUYn9hD4oa #softwaredevelopment January 13, 2020 08:24
  • http://twitter.com/codingstill

Misc Links

  • George Liatsos Blog
  • Plethora Themes
  • C# / VB Converter
  • Higlabo: .NET library for mail, DropBox, Twitter & more

Connect with me

  • GitHub
  • LinkedIn
  • RSS
  • Twitter
  • Stack Overflow

Copyright © 2021 · eleven40 Pro on Genesis Framework · WordPress · Log in