原問題:
404_vs_302_ASP_Net_Custom_Errors.aspx
解決方案:
In these days I've been experiencing a conflict between the ASP.Net architecture and the rules that search engines gurus advice to follow... I introduce you to the problem:
- Scenario: well positioned - in terms of search engines - website needs to change domain.
- Goal: we have to try as hard as we can to mantain pages' rankings gained among the various search engines.
- Remarks: all the pages are .aspx web forms.
We got informed that the search engines - let's say Google ...ok? - prefers to get a 404 response and some extra information about a possible alternative link...
Here's the ASP.Net vs Search Engines idiosyncrasy! If you handle the 404 exception the "usual way" (using customErrors section in your web.config) you get an undesired effect:
Let's say that the 404 page you set forces a 404 status code like that...
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> void Page_Load(object o, EventArgs e) { Response.StatusCode = 404; lbl.Text = Response.Status; } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>404 - Not Found</title> </head> <body> <asp:Image runat="server" ID="img" ImageUrl="~/Images/Icons/ico_warning.gif" AlternateText="404" ImageAlign="Middle" /> <asp:Label runat="server" ID="lbl" Font-Bold="true" /> </body> </html>
What you'll get is first a 302 status code (that means "redirect") and then the 404 one! (you can test it using Fiddler)
* That is to avoid in order to please search engines! *
Here it comes my solution...
The idea is to intercept a 404 HttpException via HttpModule and return the content of the 404 page written above.
Here's the IHttpModule implementation code:
using System; using System.Web; namespace PacemWebSite.BLL.Web { class PacemHttpModule : System.Web.IHttpModule { public void Dispose() { //... } public void Init(HttpApplication context) { // putting a listener to the error event: context.Error += new EventHandler(context_Error); } void context_Error(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender; Exception lastError = app.Server.GetLastError(); HttpException he = lastError as HttpException; // handling only HttpExceptions (and 404 in particular): if (he != null) { int httpErrorCode = he.GetHttpCode(); if (httpErrorCode == 404) { // clearing the error in order to avoid the exception to be thrown: app.Server.ClearError(); string fofPage = "~/Pages/404.aspx"; // setting/changing the handler for the current response: app.Context.Handler = System.Web.UI.PageParser.GetCompiledPageInstance(fofPage, app.Server.MapPath(fofPage), app.Context); } } } } }
Obviously, you must add your custom HttpModule to your Web.config as usual:
<httpModules> <add name="FourOhFourModule" type="PacemWebSite.BLL.Web.PacemHttpModule, PacemWebSite"/> </httpModules>
Now the response will be search engines pleasant with its straight 404!...
Take care. Bye.
Direct Link to this Article
Exception lastError = app.Server.GetLastError();
HttpException he = lastError as HttpException;
if (he != null)
{
app.Server.ClearError();
app.Server.Transfer(string.Format("~/GenericErrorPage.aspx?err={0}", he.GetHttpCode()));
}
<error statusCode="401" redirect="Error.aspx?ErrorCode=401" />
<error statusCode="403" redirect="Error.aspx?ErrorCode=403" />
<error statusCode="404" redirect="Error.aspx?ErrorCode=404" />
<error statusCode="408" redirect="Error.aspx?ErrorCode=408" />
<error statusCode="500" redirect="Error.aspx?ErrorCode=500" />
<error statusCode="503" redirect="Error.aspx?ErrorCode=503" />
==========
if(Request.Querystring["ErrorCode"]=="400"){
//continue code if errorcode=400
}