Asp.net URL rewriting Engine

Source: Internet
Author: User
Tags cdata
Build a URL rewriting Engine

To help describe how to implement URL rewriting in ASP. NET web applications, I have created a URL rewriting engine. This rewrite engine provides the following features:

  • The ASP. NET page developer who uses the URL rewriting engine can specify the rewrite rules in the web. config file.

  • You can use regular expressions to rewrite rules with powerful functions.

  • You can easily rewrite the URL to use the HTTP module or HTTP handler.

In this article, we will introduce the use of URL rewriting only for the HTTP module. To view how to use an HTTP handler to perform URL rewriting, refer to the code that can be downloaded with this article.

Specify configuration information for the URL rewriting Engine

Let's first introduce the structure of the rewrite rule in the web. config file. First, you must specify in the web. config file whether to use the HTTP module or HTTP processing program to rewrite the URL. In the download code, the Web. config file contains two comments:

<!--

Comment out the

In addition to specifying whether to use the HTTP module or the HTTP processing program for rewriting. the Config File also contains a rewrite rule: the rewrite rule consists of two strings: The pattern to be searched in the requested URL; the pattern string to be replaced (if found ). In the Web. config file, this information is expressed in the following syntax:

<Rewriterconfig> <rules> <rewriterrule> <lookfor> the mode to be searched </lookfor> <sendto> string to replace the mode </sendto> </rewriterrule> <rewriterrule> <lookfor> the mode to be searched </lookfor> <sendto> string to replace the mode </sendto> </rewriterrule>... </rules> </rewriterconfig>

Each rewrite rule is composed of <Rewriterrule> Element expression. The pattern to be searched by <Lookfor> The element is specified, and the string to replace the pattern found will be in <Sentto> Input in the element. These rewrite rules are calculated from start to end. If the URL matches a rule, the URL is overwritten and the search for the rewrite rule is terminated.

In <Lookfor> When specifying a pattern in an element, note that regular expressions must be used for matching and string replacement. (Later, we will introduce a real example to illustrate how to use regular expressions to search for patterns .) Since the mode is a regular expression, ensure that any reserved characters in the escape regular expression are retained. (Some regular expressions retain the following characters :.,? , ^, $, And others. You can escape these characters by adding a backslash (such as/.) to match the text periods .)

Use the HTTP module to perform URL rewriting

Create an HTTP module and create an HTTP module.IhttpmoduleThe interface class is as simple.IhttpmoduleThe interface defines two methods:

  • Init (httpapplication). This method is triggered after the HTTP module is initialized. In this method, you will bind the event handler to the correspondingHttpapplicationEvent.

  • Dispose (). This method is called when the request is complete and has been sent back to IIS. You shall perform all final cleanup operations here.

To create an HTTP module for URL rewriting, I will create an abstract base class fromBasemodulerewriterStart with introduction. This class will implementIhttpmodule. InInit ()Event, it willHttpapplicationOfAuthorizerequestBind eventsBasemodulerewriter_authorizerequestMethod.Basemodulerewriter_authorizerequestMethod to pass this class into the requestedPathOfRewrite ()Method andInit ()MethodHttpapplicationObject.Rewrite ()Methods are abstract, that is, inBasemodulerewriterClass,Rewrite ()The method does not have a method subject.BasemodulerewriterThe derived class must overwrite this method and provide the method body.

With this base class, you only need to createBasemodulerewriterThe derived class can be overwritten.Rewrite ()And execute the URL rewriting logic there. Shown belowBasemodulerewriter.

Public abstract class basemodulerewriter: ihttpmodule {Public Virtual void Init (httpapplication APP) {// warning! This code is not applicable to Windows Authentication! // If Windows authentication is used, // change it to app. beginrequest app. authorizerequest + = new eventhandler (this. principal);} Public Virtual void dispose () {} protected virtual void basemodulerewriter_authorizerequest (Object sender, eventargs e) {httpapplication APP = (httpapplication) sender; rewrite (App. request. path, APP);} protected abstract void rewrite (string requestedpath, httpapplication APP );}

Please note that,BasemodulerewriterTheAuthorizerequestURL rewriting is performed in the event. As mentioned above, if you use Windows Authentication in combination with file authorization, you need to make changes so that you canBeginrequestOrAuthenticaterequestURL rewriting is performed in the event.

ModulerewriterClass extendedBasemodulerewriterClass, and is responsible for executing the actual URL rewriting.ModulerewriterContains a single coverage method (Rewrite ()), As follows:

Protected override void rewrite (string requestedpath, system. web. httpapplication APP) {// obtain the configuration rule rewriterrulecollection rules = rewriterconfiguration. getconfig (). rules; // traverse each rule... for (INT I = 0; I <rules. count; I ++) {// obtain the mode to be searched, and // parse the URL (converted to the corresponding directory) string lookfor = "^" + rewriterutils. resolveurl (App. context. request. applicationpath, rules [I]. lookfor) + "$"; // create a RegEx (please note that ignorecase is set ...) regEx Re = new RegEx (lookfor, regexoptions. ignorecase); // check whether the matching rule if (Re. ismatch (requestedpath) {// matched rule found -- replace string sendtourl = rewriterutils as necessary. resolveurl (App. context. request. applicationpath, re. replace (requestedpath, rules [I]. sendto); // rewrite the URL rewriterutils. rewriteurl (App. context, sendtourl); break; // exit for loop }}}

Rewrite ()The method starts from obtaining a set of rewrite rules in the web. config file. Then, it will traverse the rewrite rule and traverse one at a time. For each rule, it will obtainLookforAnd use a regular expression to determine whether a matching rule is found in the requested URL.

If a matched rule is foundSendtoThe value is replaced by a regular expression in the Request Path. Then, the replaced URL will be passedRewriterutils. rewriteurl ()Method.RewriterutilsIs a helper class that provides a pair of static methods used by the URL rewrite HTTP module and HTTP handler.Rewriterurl ()Method call onlyHttpcontextObjectRewriteurl ()Method.

Note:: You may have noticed that when you perform regular expression matching and replacementRewriterutils. resolveurl (). This helper method only replaces all ~ Instance.

The whole code of the URL rewriting engine can be downloaded with this article. We have introduced most closely related components, but there are some other components (for example, for web. the XML format rewriting rules in the config file are deserialized to make it the class of the object), and the HTTP handler factory for URL rewriting. The remaining three parts of this article will introduce the actual usage of URL rewriting.

Back to the top, use the URL rewriting engine to perform simple URL rewriting.

To demonstrate the URL rewriting engine, we will build an ASP. NET web application that uses simple URL rewriting. Assume that the company we work for sells classified products through the network. These products are divided into the following categories:

CATEGORY ID

Category name

1

Beverage

2

Condiments

3

Candy

4

Dairy products

...

...

Suppose we have created an ASP. NET webpage named listproductsbycategory. aspx. This webpage accepts the category id value in the query string and displays all products of this category. Therefore, users who want to view the drinks we sell can access listproductsbycategory. aspx? Categoryid = 1, and users who want to view dairy products can access listproductsbycategory. aspx? Categoryid = 4. In addition, suppose we have a page named listcategories. aspx, which lists all product categories for sale.

Obviously, this is an example of URL rewriting, because the URLs provided to users do not make any sense to users, nor provide them with any "deletable ". Therefore, let's use URL rewriting so that when users access/products/beverages. aspx, their URL will be rewritten to listproductsbycategory. aspx? Categoryid = 1. We can use the following URL rewriting rules in the web. config file to implement this function.

<Rewriterconfig> <rules> <! -- Product tabulation rule --> <rewriterrule> <lookfor> ~ /Products/beverages/. aspx </lookfor> <sendto> ~ /Listproductsbycategory. aspx? Categoryid = 1 </sendto> </rewriterrule> </rules> </rewriterconfig>

As you can see, this rule will be searched to check whether the path of the user request is/products/beverages. aspx. If yes, it will rewrite the URL to/listproductsbycategory. aspx? Categoryid = 1.

Note:: Note: <Lookfor> The element escapes the periods in beverages. aspx. This is because <Lookfor> Value, and the period is a special character in the regular expression. This character indicates "matching any character", for example, matching with URL/products/beveragesqaspx. The escape period (use/.) indicates that we want to match a text period, rather than any old character.

With this rule, when you access/products/beverages. aspx, drinks for sale are displayed on the page. Figure 3 shows a snapshot of the browser accessing/products/beverages. aspx. Please note that in the address bar of the browser, the URL will read/products/beverages. aspx, But what you actually see is listproductsbycategory. aspx? Content of categoryid = 1. (In fact, The/products/beverages. aspx file does not exist on the Web server !)

Figure 3. Request category after URL rewriting

Similar to/products/beverages. aspx, we will add rewrite rules for other product categories. This operation only includes adding additional <rules> elements to the Web. config file.Rewriterrule> Element. See the web. config file in the downloaded content to obtain a complete set of rewrite rules for this demonstration.

To make the URL more deletable, it is recommended that you delete beverages. aspx from/products/beverages. aspx to see the list of product categories. At first glance, this may be a very common task (you only need to add a rewrite rule that maps/products/to/listcategories. aspx ). However, this operation has a subtle point: you must first create a/products/directory and add an empty default. aspx file to the/products/directory.

To understand the reason for executing these additional steps, refer to the previous content, that is, the URL rewriting engine is located at the ASP. NET level. That is to say, if the ASP. NET engine never has the opportunity to process the request, the URL rewriting engine cannot detect the passed URL. Also, remember that IIS will pass the incoming request to the ASP. net engine only when the requested file has a corresponding extension. Therefore, if the user accesses/products/and IIS does not see any file extension, it will check the directory to see whether such a file exists, that is, the file name is one of the default file names. (Default.aspx1_default.htm, default. asp, and so on. The "documents" tab of the "Web Server properties" dialog box in the "IIS management" dialog box defines these default file names .) Of course, if the/products/directory does not exist, IIS will return an HTTP 404 error.

Therefore, we need to create the/products/directory. In addition, we also need to create a file default. aspx in this directory. In this way, when you access/products/, IIS will check the directory to check whether a file named default. aspx exists, and then pass the processing process to the ASP. NET engine. Then, the URL rewriter will break down when rewriting the URL.

After creating the Directory and the default. aspx file, proceed with the operation andRules> Add the following rewrite rules to the element:

<RewriterRule>   <LookFor>~/Products/Default/.aspx</LookFor>   <SendTo>~/ListCategories.aspx</SendTo></RewriterRule>

With this rule, when users access/products/or/products/default. aspx, they will see the product category list, as shown in 4.

Figure 4.Add "deletable" to the URL to process sending back

If the URL to be rewritten contains a web form on the server side and the form is resent, The underlined URL is used. That is, if you enter/products/beverages in the browser. aspx. What they will see in the address bar of the browser is/products/beverages. aspx, but the content they see will be listproductsbycategory. aspx? Content of categoryid = 1. If listproductsbycategory. aspx executes sending back, the user will be sent back to listproductsbycategory. aspx? Categoryid = 1 instead of/products/beverages. aspx. This will not interrupt any content, but from the user's perspective, if you suddenly see the URL change when you click the button, it will make them feel uneasy.

The reason for this is that when a web form is displayed, it directly sets its operation attribute to the file path value in the request object. Of course, when rendering a web form, the URL has been rewritten from/products/beverages. aspx to listproductsbycategory. aspx? Categoryid = 1, which indicates that the request object reports that the user wants to access listproductsbycategory. aspx? Categoryid = 1. This problem can be solved simply by making the server-side form not present operation properties. (By default, if the form does not contain operation attributes, the browser will send back .)

Unfortunately, the web form does not allow you to explicitly specify operation properties or set certain properties to disable the rendering of operation properties. Therefore, we must extend the system. Web. htmlcontrols. htmlform class by ourselves to overwrite the renderattribute () method and explicitly state that it will not render the operation attribute.

Because of the inheritance function, we can obtain all the functions of the htmlform class, and only need to add a few lines of code to obtain the required behavior. The complete code for the custom class is shown below:

namespace ActionlessForm {  public class Form : System.Web.UI.HtmlControls.HtmlForm  {     protected override void RenderAttributes(HtmlTextWriter writer)     {        writer.WriteAttribute("name", this.Name);        base.Attributes.Remove("name");        writer.WriteAttribute("method", this.Method);        base.Attributes.Remove("method");        this.Attributes.Render(writer);        base.Attributes.Remove("action");        if (base.ID != null)           writer.WriteAttribute("id", base.ClientID);     }  }}

OverwrittenRenderattributes ()The method code only containsHtmlformClassRenderattributes ()Method, without setting operation attributes. (I use {
Track ('ctl00 _ mtcs_main_ctl00 | ctl00_mtcs_main_ctl12 ', this );
} "Href =" http://www.aisto.com/roeder/DotNet/ "> reflector to viewHtmlformClass source code .)

After creating and compiling this class, you must first add it to the references folder of the Web application to use it in the ASP. NET web application. Then, use it instead.HtmlformClass. You only need to add the following content to the top of the ASP. NET webpage:

<%@ Register TagPrefix="skm" Namespace="ActionlessForm"    Assembly="ActionlessForm" %>

Then, replace <form runat = "server"> (if any):

<skm:Form id="Form1" method="post" runat="server">

And replace the </form> mark on the right:

</skm:Form>

You can find this custom web form class in the listproductsbycategory. aspx (included in the download code in this article) operation. The downloaded content also contains the Visual Studio. Net project for no web form operation.

Note:: If the target URL to be rewritten is not re-sent, you do not need to use this custom web form class.

Return to the top page to create a URL with a real "deletable"

The simple URL rewriting described in the previous section shows how to easily configure new Rewrite Rules for the URL rewriting engine. However, when using a regular expression, the real function of the rewrite rule will play a greater role. This part will discuss this.

Blog is becoming more and more popular today. It seems that everyone has their own blog. If you are not familiar with blog: a blog is a personal page that is frequently updated and usually used as an online journal. Most blogs only record what happens every day, and some blogs may focus on specific topics (such as movie review, sports team, or computer technology ).

You can update a blog anywhere. The update frequency ranges from several times a day to once or twice a week. The specific situation depends on the author. Generally, the blog homepage displays the last 10 entries, but in fact, all blog software provides archives, allowing visitors to read earlier posts through archives. A blog is a powerful application used to delete a URL. Assume that you find yourself on the URL/2004/02/14. aspx when searching for the Blog Archive. Are you surprised to find that you are reading the post in February 14, 2004? In addition, you may want to view all posts in June February 2004. In this case, you can try to delete the URL as/2004/02 /. To view all the posts in June 2004, you can try to access/2004 /.

When maintaining a blog, it is best to provide visitors with a URL of this level that can be deleted ". Many blog engines provide this function, but we will discuss how to use URL rewriting to implement this function.

First, we need an ASP. NET webpage, which displays blog entries by day, month, or year. Suppose we have a showblogcontent. ASPX page, where the query string parameters are year, month, and day. To view the Post published in May February 14, 2004, Can we access showblogcontent. aspx? Year = 2004 & month = 2 & day = 14. To view all posts in February 2004, Can we access showblogcontent. aspx? Year = 2004 & month = 2. Finally, to view all posts in 2004, we can browse showblogcontent. aspx? Year = 2004. (You can find the showblogcontent. aspx code in the download content of this article .)

In this case, if the user accesses/2004/02/14. aspx, We need to rewrite the URL to showblogcontent. aspx? Year = 2004 & month = 2 & day = 14. All three cases (the URL specifies the year, month, and day; the URL only specifies the year and month; the URL only specifies the year) can be processed using the rewrite rule:

<Rewriterconfig> <rules> <! -- Program rules for Blog content display --> <rewriterrule> <lookfor> ~ /(/D {4})/(/d {2})/(/d {2})/. aspx </lookfor> <sendto> ~ /Showblogcontent. aspx? Year = $1 & amp; month = $2 & amp; Day = $3 </sendto> </rewriterrule> <lookfor> ~ /(/D {4})/(/d {2})/default/. aspx </lookfor> <sendto> <! [CDATA [~ /Showblogcontent. aspx? Year = $1 & month = $2]> </sendto> </rewriterrule> <lookfor> ~ /(/D {4})/default/. aspx </lookfor> <sendto> ~ /Showblogcontent. aspx? Year = $1 </sendto> </rewriterrule> </rules> </rewriterconfig>

These Rewrite Rules indicate the function of the regular expression. In the first rule, we use the mode (/d {4})/(/d {2})/(/d {2})/. aspx to find the URL. In concise English, it corresponds to a string of four numbers, followed by a slash, followed by two numbers, followed by a slash, followed by two numbers, and finally one. aspx. Brackets around each number Group are very important. You can use the brackets in the corresponding <Sendto> Attribute references matching characters in these parentheses. In particular, we can use $1, $2, and $3 to reference the matching groups in the parentheses for the first, second, and third parentheses respectively.

Note:: Because the Web. config file uses XML format, characters (such as &, <, and>) in the element text must be escaped. <Sendto> In the element, & is escaped as & amp ;. <Sendto> Another technology is used. <! [CDATA [...]> Element), you do not need to escape the internal content. You can use either of the two methods and get the same result.

Figure 5, 6, and 7 show URL rewriting in the action. The data is actually from my blog {
Track ('ctl00 _ mtcs_main_ctl00 | ctl00_mtcs_main_ctl13 ', this );
} "Href =" http://scottonwriting.net/"> dragged in the http://scottonwriting.net. Figure 5 shows the November 7, 2003 posts; Figure 6 shows all posts in November 2003; Figure 7 shows all posts in 2003.

Figure 5.Post in November 7, 2003

Figure 6.All posts in November 2003

Figure 7.All posts in 2003

Note:: The URL rewriting engine is in the <Lookfor> The regular expression mode must be used in the element. If you are not familiar with regular expressions, read an article I wrote earlier {
Track ('ctl00 _ mtcs_main_ctl00 | ctl00_mtcs_main_ctl14 ', this );
} "Href =" http://www.4guysfromrolla.com/webtech/090199-1.shtml "> An Introduction to regular expressions. In addition, there is a good website :{
Track ('ctl00 _ mtcs_main_ctl00 | ctl00_mtcs_main_ctl15 ', this );
} "Href =" http://regexlib.com/"> regexlib.com, where you can get help information about common Regular Expressions and share your own custom regular expressions.

Build essential directory structures

When the request is/2004/03/19. aspx, IIS will notify the. aspx extension and route the request to the ASP. NET engine. When a request is moved in an ASP. NET Engine Pipeline, the URL will be rewritten to showblogcontent. aspx? Year = 2004 & month = 03 & day = 19, and visitors will see the March 19, 2004 blog entry. But what happens when the user browses/2004/03? IIS returns a 2004/03 error unless there is a/404/directory. In addition, this directory also requires a default. aspx page to pass requests to the ASP. NET engine.

Therefore, to use this method, you must manually create a directory (including blog entries) for each year, and the directory contains a default. aspx page. In addition, you need to manually create 12 directories (01, 02 ,? ,?... , 12), and each directory contains a default. aspx file. (As described above, you must add a default. aspx file to the/products/directory to display listcategories. aspx correctly when accessing/products .)

Obviously, adding such a directory structure may be very painful. To solve this problem, all incoming IIS requests are mapped to the ASP. NET engine. In this way, IIS will pass requests to the ASP. NET engine (even if the/2004/03/directory does not exist) even if the URL/2004/03/is accessed ). However, this method enables the ASP. net engine to process all types of incoming requests to the Web server, including images, CSS files, external JavaScript files, and Macromedia Flash files.

The comprehensive discussion of processing all file types is far beyond the scope of this article. For examples of ASP. NET web applications that use this technology, see. text, an open source blog engine. {
Track ('ctl00 _ mtcs_main_ctl00 | ctl00_mtcs_main_ctl16 ', this );
} "Href =" http://www.gotdotnet.com/community/workspaces/default.aspx ">. text can be configured to map all requests to the ASP. NET engine. It can use a custom HTTP handler to process the issue of generating all file types. Custom HTTP handlers learn how to generate typical static file types (images, CSS files, and so on ).

Back to Top conclusion

In this article, we discuss how to passHttpcontextClassRewriteurl ()Method to rewrite the URL. As we can see,Rewriteurl ()Updated the specifiedHttpcontext's requestTo update the requested file and path. The final result is that, from the user's perspective, they want to access a specific URL, but from the Web server side, the requested URL is another.

You can rewrite the URL in the HTTP module or HTTP processing program. In this article, we will introduce how to use the HTTP module to execute rewriting and discuss the results of executing rewriting at different stages in the pipeline.

Of course, if ASP. NET rewrite is executed, URL rewriting will only occur if the request has been successfully passed from IIS to the ASP. NET engine. In fact, this happens only when the user requests a page with the. aspx extension. However, if you want to enable the user to access a URL that does not actually exist, but want to rewrite it to the existing ASP.. NET page, you must create a virtual directory and default. ASPX page, or configure IIS to route all incoming requests to ASP.. net engine.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.