HTTPModule: Redirect a page even if POST ed
October 12, 2010 by: B.HardingMy curret project involves an HTTP module that will handle page redirects that are centrally manage by storing them in a database.
I want the module also handle redirects for form submits that use both get and post.
Get is easy, you just pull off the querry string and tack it back on when you’ve found the new page. Post isn’t so easy.
In html when you use <form method=”post” things change completely behind the scenes. Because of this a 301 message won’t do. When a client receives this message it does a get on the new page and the form data is lost.
Server.Transfer will not work for me because I need the module to redirect to a full url. This causes a runtime error when server.transfer is used even if the full url is the same server.
The best solution I’ve found is to use 307 temporarily moved if the original method was “post”.
According to the HTTP 1.1 RFC a browser must confirm re-posting to the new location. If the user confirms the new location is used. I tested this on 5 browsers, Firefox, Opera, Safari, IE, and Chrome.
Only Firefox and Opera followed the RFC. IE, Safari and Chrome simply redirect the post as if nothing happened.
Here is the source from the module…
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
using Sample.Data.Web;
namespace Sample.Web.HttpHandlers
{
public class RedirectModule : IHttpModule
{
#region under the hood settings
public void Init(HttpApplication app)
{
app.BeginRequest += new EventHandler(OnBeginRequest);
}
public void Dispose() { }
#endregion
public void OnBeginRequest(Object sender, EventArgs e)
{
HttpApplication context = sender as HttpApplication;
try
{
string requestMethod = context.Request.RequestType;
string requestUrl = context.Request.Url.ToString().ToLower();
string protocol = context.Request.Url.Scheme;
string host = context.Request.Url.Authority;
string file = context.Request.Url.LocalPath;
string query = context.Request.Url.Query;
string strippedRequest = protocol + "://" + host + file;
using (SampleWebEntities db = new SampleWebEntities())
{
var redirect = (
from u in db.UrlRedirects
where u.RequestServer.ToLower().Contains(host.ToLower()) &&
u.RequestUrl.ToLower()==file
select u
).FirstOrDefault();
if (redirect != null)
{
context.Response.Clear();
if (requestMethod == "POST")
{
context.Response.Status = "307 Temporary Redirect";
}
else
{
context.Response.Status = "301 Moved Permanently";
}
context.Response.AddHeader("Location", redirect.ResponseUrl + query);
context.Response.AddHeader("Cache-Control", "no-cache");
context.Response.End();
}
}
}
catch (Exception ex)
{
//TODO: Handle Exception
string str = ex.ToString();
}
}//OnBeginRequest
}//class
}//Namespace


