在ASP.NET 4.0中使用%20和%3F处理URL错误的正确方法

时间:2013-11-23 04:22:27

标签: asp.net asp.net-4.0

我网站上90%的网页都遵循这种语法

http://www.thisismysite.com/ShowProduct.aspx?ID=29
http://www.thisismysite.com/BrowseProducts.aspx?CatID=58

我正在查看Google网站管理员工具,发现我的网站正在为以下网址生成错误

http://www.thisismysite.com/ShowProduct.aspx%20ID=50
http://www.thisismysite.com/BrowseProducts.aspx%20CatID=58
http://www.thisismysite.com/ShowProduct.aspx%3FID%3D900
http://www.thisismysite.com/ShowProduct.aspx%3FID=727
http://www.thisismysite.com/ShowProduct.aspx%3FID=64
http://www.thisismysite.com/GetProductsRss.aspx%3FCatID%3D60

当我浏览这些网址时,我收到了错误

'/'应用程序中的服务器错误。

运行时错误 描述:处理您的请求时发生异常。此外,执行第一个异常的自定义错误页面时发生另一个异常。请求已被终止。

如何修复这些错误?我知道relaxedUrlToFileSystemMapping="true",但这不是一个黑客?什么是处理这些网址的正确方法

我的web.config的一部分看起来像这样

<system.web>
<httpRuntime requestValidationMode="2.0" />
<authentication mode="Forms">
    <forms cookieless="UseCookies" loginUrl="~/AccessDenied.aspx" name="TBFORMAUTH" />
</authentication>
<pages theme="TemplateM" masterPageFile="~/Template.master"   maintainScrollPositionOnPostBack="false" validateRequest="false"   enableEventValidation="false" viewStateEncryptionMode="Never"   controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">  
</pages>
<!--
Possible modes are "transitional", "strict", and "legacy".
<xhtmlConformance mode="transitional" />
-->
<compilation debug="false" targetFramework="4.0">           
    <assemblies>
        <add assembly="System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C53R34E089" /></assemblies></compilation>


<sessionState mode="InProc" cookieless="false" timeout="15" />
<roleManager enabled="true" cacheRolesInCookie="true" cookieName="TBROLES" defaultProvider="TB_RoleProvider">
    <providers>
        <add connectionStringName="LocalSqlServer" applicationName="/" name="TB_RoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f22f50a3a" />
    </providers>
</roleManager>
<anonymousIdentification cookieless="UseCookies" enabled="false" />
<profile defaultProvider="TB_ProfileProvider">
    <providers>
        <add name="TB_ProfileProvider" connectionStringName="LocalSqlServer" applicationName="/" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f64f1d50a3a" />
    </providers>
    <properties>
        <add name="FirstName" type="String" />
        <add name="LastName" type="String" />
        <add name="Gender" type="String" />
        <add name="BirthDate" type="DateTime" />
        <add name="Occupation" type="String" />
        <add name="Website" type="String" />

        <group name="Forum">
            <add name="Posts" type="Int32" />
            <add name="AvatarUrl" type="String" />
            <add name="Signature" type="String" />
        </group>
        <group name="Address">
            <add name="Street" type="String" />
            <add name="PostalCode" type="String" />
            <add name="City" type="String" />
            <add name="State" type="String" />
            <add name="Country" type="String" />
        </group>
        <group name="Contacts">
            <add name="Phone" type="String" />
            <add name="Fax" type="String" />
        </group>
        <group name="Preferences">
            <add name="Theme" type="String" allowAnonymous="false" />
            <add name="Culture" type="String" defaultValue="en-US" />
        </group>
    </properties>
</profile>
<webParts enableExport="true">
    <personalization defaultProvider="TB_PersonalizationProvider">
        <providers>
            <add name="TB_PersonalizationProvider" connectionStringName="LocalSqlServer" type="System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
        <authorization>
            <allow roles="Administrators,Editors" verbs="enterSharedScope" />
        </authorization>
    </personalization>
</webParts>
<machineKey validationKey="287C5D125D6B7E7223E1F719E3D58D17BB9677030175D6B7E7223E1F719E3D58D17BBC7E59800B5D4C2EDD5B5D6B7E7223E1F719E3D58D17BBBAF260D9D374A74C76CB741803" decryptionKey="5C1D8BD9DF3E1B4E1D05C1D8BD9DF616E0D5C1D8BD9DF" validation="SHA1" />

<customErrors defaultRedirect="~/Error.aspx" redirectMode="ResponseRewrite">
</customErrors>

<urlMappings>
    <add url="~/articles/beer.aspx" mappedUrl="~/BrowseProducts.aspx?CatID=28" />
    <add url="~/articles/events.aspx" mappedUrl="~/BrowseProducts.aspx?CatID=41" />
    <add url="~/articles/news.aspx" mappedUrl="~/BrowseProducts.aspx?CatID=31" />
    <add url="~/articles/photos.aspx" mappedUrl="~/BrowseProducts.aspx?CatID=40" />
    <add url="~/articles/blog.aspx" mappedUrl="~/BrowseProducts.aspx?CatID=29" />
    <add url="~/articles/faq.aspx" mappedUrl="~/BrowseProducts.aspx?CatID=42" />
</urlMappings>
<healthMonitoring heartbeatInterval="10800">
    <providers>
        <remove name="SqlWebEventProvider" />
        <add name="SqlWebEventProvider" connectionStringName="LocalSqlServer" buffer="false" bufferMode="Notification" maxEventDetailsLength="1073741823" type="System.Web.Management.SqlWebEventProvider,System.Web,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7fse350a3a" />
    </providers>
    <eventMappings>
        <add name="TB Events" type="MB.Customs.WebCustomEvent, MB.Customs.CustomEvents" />
    </eventMappings>
    <rules>
        <clear />
        <add name="TB Events" eventName="TB Events" provider="SqlWebEventProvider" profile="Critical" />
        <add name="All Errors" eventName="All Errors" provider="SqlWebEventProvider" profile="Critical" />
        <add name="Failure Audits" eventName="Failure Audits" provider="SqlWebEventProvider" profile="Critical" />
        <add name="Heartbeats" eventName="Heartbeats" provider="SqlWebEventProvider" profile="Critical" />
    </rules>
</healthMonitoring>
</system.web>

1 个答案:

答案 0 :(得分:0)

由于这些外部链接是URL编码的,因此ASP.NET将尝试查找具有该名称的文件或路由。您可以尝试使用路由框架来巧妙地查找以应用程序中的路由开头的URL。但是,这可能意味着每个页面都需要其他逻辑来解析不正确编码的请求。另一个解决方案是为您在知道如何最好地重定向用户时生成的404添加自定义错误处理。

您可以处理此错误的最佳方法可能是拦截Applications Global.asax.cs文件中的错误。您可以在Application_Error方法中尝试以下内容:

protected void Application_Error(Object sender, EventArgs e) 
{
    bool httpError = Context.Error is HttpException;
    if (httpError && ((HttpException)Context.Error).GetHttpCode() == 404)
    {
        // Convert the path to lowercase. This should ONLY be used to make finding indices easier, but NOT used when generating the redirect path since case could be important.
        string absolutePath = Request.Url.AbsolutePath.ToLowerInvariant();
        int extensionLength = ".aspx".Length;
        int questionMarkIdx = absolutePath.IndexOf("?");
        int encodedQuestionMarkIdx = absolutePath.IndexOf(".aspx%3F") + extensionLength;
        int encodedSpaceIdx = absolutePath.IndexOf(".aspx%20") + extensionLength;
        // Handle encoded question mark
        if ((questionMarkIdx == -1) && (encodedQuestionMarkIdx > extensionLength))
        {
            string correctPath = Request.Url.AbsolutePath.Substring(0, absolutePath.Length - encodedQuestionMarkIdx);
            // Add 3 here to exclude the "%3F" in the result
            string encodedQueryString = Request.Url.AbsolutePath.Substring(encodedQuestionMarkIdx + 3);
            Response.Redirect(correctPath + "?" + HttpUtility.UrlDecode(encodedQueryString));
        }
        // Handle encoded space
        if ((questionMarkIdx == -1) && (encodedSpaceIdx > extensionLength))
        {
            string correctPath = Request.Url.AbsolutePath.Substring(0, absolutePath.Length - encodedSpaceIdx);
            // Add 3 here to exclude the "%20" in the result
            string encodedQueryString = Request.Url.AbsolutePath.Substring(encodedSpaceIdx + 3);
            Response.Redirect(correctPath + "?" + HttpUtility.UrlDecode(encodedQueryString));
        }
    }
}

我在非Windows机器上写了这个答案,所以我没有办法测试它,但这应该足以让你朝着解决这个问题的方向前进。

重要的一点是要区分发生的404,因为URL编码不正确,而404因为你无法处理的其他一般原因而发生。由于URL编码问题,您只想处理404。所有其他错误和其他404消息应该传播回默认处理程序。

另一个重要的事情是检查引用者对这些错误URL的请求是什么。您应该查看Google网站管理员工具,看看他们是否会告诉您。如果他们不这样做,你需要检查你的日志(或确保你做一些!),以找出他们来自哪里。了解源代码后,您应该与网站所有者联系,让他们知道他们正在提供错误的网址。试图弥补损坏的外部链接并非万无一失,并且是一项非常困难的挑战,可以自己成为一份全职工作,因此如果它在你的权力范围内,你最好不要试图阻止它们被生成实现它。