using System;
using System.Configuration;
using System.Collections;
namespace URLRewriter.Config
{
// Define a custom section containing a simple element and a collection of the same element.
// It uses two custom types: UrlsCollection and UrlsConfigElement.
public class UrlsConfig
{
public static UrlsSection GetConfig()
{
return (UrlsSection)System.Configuration.ConfigurationManager.GetSection("CustomConfiguration");
}
}
public class UrlsSection : ConfigurationSection
{
[ConfigurationProperty("urls",IsDefaultCollection = false)]
public UrlsCollection Urls
{
get
{
return (UrlsCollection)this["urls"];
}
}
}
// Define the UrlsCollection that contains UrlsConfigElement elements.
public class UrlsCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new UrlConfigElement();
}
protected override Object GetElementKey(ConfigurationElement element)
{
return ((UrlConfigElement)element).VirtualUrl;
}
public UrlConfigElement this[int index]
{
get
{
return (UrlConfigElement)BaseGet(index);
}
}
}
// Define the UrlConfigElement.
public class UrlConfigElement : ConfigurationElement
{
[ConfigurationProperty("virtualUrl", IsRequired = true)]
public string VirtualUrl
{
get
{
return (string)this["virtualUrl"];
}
set
{
this["virtualUrl"] = value;
}
}
[ConfigurationProperty("destinationUrl", IsRequired = true)]
public string DestinationUrl
{
get
{
return (string)this["destinationUrl"];
}
set
{
this["destinationUrl"] = value;
}
}
}
}
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/// <summary>
/// FormRewriter 的摘要说明
/// </summary>
namespace URLRewriter.Form
{
public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter
{
public FormRewriterControlAdapter()
{
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(new RewriteFormHtmlTextWriter(writer));
}
}
public class RewriteFormHtmlTextWriter : HtmlTextWriter
{
public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
: base(writer)
{
base.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 = HttpContext.Current;
if (context.Items["ActionAlreadyWritten"] == null)
{
//We will use the Request.RawUrl property within ASP.NET to retrieve the origional
//URL before it was re-written.
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);
}
}
}
using System;
using System.Web;
using System.Text.RegularExpressions;
using System.Configuration;
using URLRewriter.Config;
namespace URLRewriter
{
public class RewriterModule : IHttpModule
{
public void Init(HttpApplication app)
{
// WARNING! This does not work with Windows authentication!
// If you are using Windows authentication, change to app.BeginRequest
app.AuthorizeRequest += new EventHandler(this.URLRewriter);
}
protected void URLRewriter(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication) sender;
string requestedPath = app.Request.Path;
// get the configuration rules
UrlsCollection rules = UrlsConfig.GetConfig().Urls;
for (int i = 0; i < rules.Count; i++)
{
// get the pattern to look for, and Resolve the Url (convert ~ into the appropriate directory)
string lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].VirtualUrl) + "$";
Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);
if (re.IsMatch(requestedPath))
{
string sendToUrl = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules[i].DestinationUrl));
RewriterUtils.RewriteUrl(app.Context, sendToUrl);
break;
}
}
}
public void Dispose() { }
}
/// <summary>
/// Provides utility helper methods for the rewriting HttpModule and HttpHandler.
/// </summary>
/// <remarks>This class is marked as internal, meaning only classes in the same assembly will be
/// able to access its methods.</remarks>
internal class RewriterUtils
{
#region RewriteUrl
/// <summary>
/// Rewrite's a URL using <b>HttpContext.RewriteUrl()</b>.
/// </summary>
/// <param name="context">The HttpContext object to rewrite the URL to.</param>
/// <param name="sendToUrl">The URL to rewrite to.</param>
internal static void RewriteUrl(HttpContext context, string sendToUrl)
{
string x, y;
RewriteUrl(context, sendToUrl, out x, out y);
}
/// <summary>
/// Rewrite's a URL using <b>HttpContext.RewriteUrl()</b>.
/// </summary>
/// <param name="context">The HttpContext object to rewrite the URL to.</param>
/// <param name="sendToUrl">The URL to rewrite to.</param>
/// <param name="sendToUrlLessQString">Returns the value of sendToUrl stripped of the querystring.</param>
/// <param name="filePath">Returns the physical file path to the requested page.</param>
internal static void RewriteUrl(HttpContext context, string sendToUrl, out string sendToUrlLessQString, out string filePath)
{
// see if we need to add any extra querystring information
if (context.Request.QueryString.Count > 0)
{
if (sendToUrl.IndexOf('?') != -1)
sendToUrl += "&" + context.Request.QueryString.ToString();
else
sendToUrl += "?" + context.Request.QueryString.ToString();
}
// first strip the querystring, if any
string queryString = String.Empty;
sendToUrlLessQString = sendToUrl;
if (sendToUrl.IndexOf('?') > 0)
{
sendToUrlLessQString = sendToUrl.Substring(0, sendToUrl.IndexOf('?'));
queryString = sendToUrl.Substring(sendToUrl.IndexOf('?') + 1);
}
// grab the file's physical path
filePath = string.Empty;
filePath = context.Server.MapPath(sendToUrlLessQString);
// rewrite the path...
context.RewritePath(sendToUrlLessQString, String.Empty, queryString);
}
#endregion
/// <summary>
/// Converts a URL into one that is usable on the requesting client.
/// </summary>
/// <remarks>Converts ~ to the requesting application path. Mimics the behavior of the
/// <b>Control.ResolveUrl()</b> method, which is often used by control developers.</remarks>
/// <param name="appPath">The application path.</param>
/// <param name="url">The URL, which might contain ~.</param>
/// <returns>A resolved URL. If the input parameter <b>url</b> contains ~, it is replaced with the
/// value of the <b>appPath</b> parameter.</returns>
internal static string ResolveUrl(string appPath, string url)
{
if (url.Length == 0 || url[0] != '~')
return url; // there is no ~ in the first character position, just return the url
else
{
if (url.Length == 1)
return appPath; // there is just the ~ in the URL, return the appPath
if (url[1] == '/' || url[1] == '//')
{
// url looks like ~/ or ~/
if (appPath.Length > 1)
return appPath + "/" + url.Substring(2);
else
return "/" + url.Substring(2);
}
else
{
// url looks like ~something
if (appPath.Length > 1)
return appPath + "/" + url.Substring(1);
else
return appPath + url.Substring(1);
}
}
}
}
}