使用URL Rewrite和404.aspx时回发问题

时间:2022-11-24 00:21:04

I'm using URL rewrite on my site to get URLs like:
http://mysite.com/users/john
instead of
http://mysite.com/index.aspx?user=john

我在我的网站上使用URL重写来获取以下URL:http://mysite.com/users/john而不是http://mysite.com/index.aspx?user=john

To achive this extensionless rewrite with IIS6 and no access to the hosting-server I use the "404-approach". When a request that the server can't find, the mapped 404-page is executed, since this is a aspx-page the rewrite can be performed (I can setup the 404-mapping using the controlpanel on the hosting-service).

要使用IIS6实现这种无扩展的重写并且无法访问托管服务器,我使用“404-approach”。当服务器找不到请求时,执行映射的404页面,因为这是一个aspx页面,可以执行重写(我可以使用托管服务上的控制面板设置404映射)。

This is the code in Global.asax:

这是Global.asax中的代码:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    string url = HttpContext.Current.Request.Url.AbsolutePath;
    if (url.Contains("404.aspx"))
    {
        string[] urlInfo404 = Request.Url.Query.ToString().Split(';');
        if (urlInfo404.Length > 1)
        {
            string requestURL = urlInfo404[1];
            if (requestURL.Contains("/users/"))
            {
                HttpContext.Current.RewritePath("~/index.aspx?user=" + GetPageID(requestURL));              
                StoreRequestURL(requestURL);
            }
            else if (requestURL.Contains("/picture/"))
            {
                HttpContext.Current.RewritePath("~/showPicture.aspx?pictureID=" + GetPageID(requestURL));
                StoreRequestURL(requestURL);
            }
        }
    }
}

private void StoreRequestURL(string url)
{
    url = url.Replace("http://", "");
    url = url.Substring(url.IndexOf("/"));
    HttpContext.Current.Items["VirtualUrl"] = url;
}

private string GetPageID(string requestURL)
{
    int idx = requestURL.LastIndexOf("/");
    string id = requestURL.Substring(idx + 1);
    id = id.Replace(".aspx", ""); //Only needed when testing without the 404-approach
    return id;
}

And in Page_Load on my masterpage I set the correct URL in the action-attribute on the form-tag.

在我的母版页上的Page_Load中,我在form-tag的action-attribute中设置了正确的URL。

protected void Page_Load(object sender, EventArgs e)
{
    string virtualURL = (string)HttpContext.Current.Items["VirtualUrl"];
    if (!String.IsNullOrEmpty(virtualURL))
    {
        form1.Action = virtualURL;
    }
}

The rewrite works fine but when I perform a postback on the page the postback isn't executed, can this be solved somehow?

重写工作正常,但是当我在页面上执行回发时,不会执行回发,这可以以某种方式解决吗?

The problem seems to be with the 404-approach because when I try without it (and loses the extensionless-feature) the postback works. That is when I request:
http://mysite.com/users/john.aspx

问题似乎与404方法有关,因为当我尝试没有它(并且失去无扩展功能)时,回发工作。那是我要求的时候:http://mysite.com/users/john.aspx

Can this be solved or is there any other solution that fulfil my requirements (IIS6, no serveraccess/ISAPI-filter and extensionless).

这可以解决,还是有任何其他解决方案满足我的要求(IIS6,没有serveraccess / ISAPI过滤器和无扩展)。

7 个解决方案

#1


form1.Action = Request.RawUrl

in combination with

与...结合

HttpContext.Current.RewritePath("/Default.aspx", true); 

works very well for me.

对我来说效果很好。

setting the form Action attribute was the piece i was missing...

设置表单Action属性是我缺少的那个...

Thanks for the solution!!!

谢谢你的解决方案!

#2


Scott Guthrie covers different ways of doing this here without IIS access:

Scott Guthrie在没有IIS访问的情况下介绍了不同的方法:

http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx

Personally, I've created HTTPModules in the past and it's pretty easy to put together.

就个人而言,我过去创建了HTTPModules,它很容易组合在一起。

#3


form1.Action = Request.RawUrl is also how it is written in C# put it in the page load method

form1.Action = Request.RawUrl也是如何用C#编写的把它放在页面加载方法中

#4


I would start by installing Live Http Headers and see whats going on with the Http requests.

我将首先安装Live Http Headers并查看Http请求的最新情况。

Ahh here in that article it explains it, looks like the action attribute of the form tag is wrong:

啊,在那篇文章中它解释了它,看起来像form标签的action属性是错误的:

One gotcha that people often run into when using ASP.NET and Url-Rewriting has to-do with handling postback scenarios. Specifically, when you place a <form runat="server"> control on a page, ASP.NET will automatically by default output the "action" attribute of the markup to point back to the page it is on. The problem when using URL-Rewriting is that the URL that the control renders is not the original URL of the request (for example: /products/books), but rather the re-written one (for example: /products.aspx?category=books). This means that when you do a postback to the server, the URL will not be your nice clean one.

人们经常在使用ASP.NET和Url-Rewriting时遇到的问题与处理回发场景有关。具体来说,当您在页面上放置

控件时,ASP.NET将自动默认输出标记的“action”属性以指向它所在的页面。使用URL重写时的问题是控件呈现的URL不是请求的原始URL(例如:/ products / books),而是重写的URL(例如:/products.aspx?category =书籍)。这意味着当您对服务器进行回发时,URL将不是您干净利落的URL。

With ASP.NET 1.0 and 1.1, people often resorted to sub-classing the <form> control and created their own control that correctly output the action to use. While this works, it ends up being a little messy - since it means you have to update all of your pages to use this alternate form control, and it can sometimes have problems with the Visual Studio WYSIWYG designer.

在ASP.NET 1.0和1.1中,人们经常使用

控件进行子类化并创建自己的控件来正确输出要使用的操作。虽然这有效,但最终会有点混乱 - 因为这意味着您必须更新所有页面以使用此备用表单控件,并且有时可能会遇到Visual Studio WYSIWYG设计器的问题。

The good news is that with ASP.NET 2.0, there is a cleaner trick that you can use to rewrite the "action" attribute on the <form> control. Specifically, you can take advantage of the new ASP.NET 2.0 Control Adapter extensibility architecture to customize the rendering of the <form> control, and override its "action" attribute value with a value you provide. This doesn't require you to change any code in your .aspx pages. Instead, just add a .browser file to your /app_browsers folder that registers a Control Adapter class to use to output the new "action" attribute...

好消息是,使用ASP.NET 2.0,您可以使用更清晰的技巧重写

控件上的“action”属性。具体来说,您可以利用新的ASP.NET 2.0控件适配器可扩展性体系结构来自定义控件的呈现,并使用您提供的值覆盖其“action”属性值。这不需要您更改.aspx页面中的任何代码。相反,只需将.browser文件添加到/ app_browsers文件夹中,该文件夹注册一个Control Adapter类,用于输出新的“action”属性...

#5


You could just use the below instead:

您可以使用以下代替:

form1.Action = Request.RawUrl

form1.Action = Request.RawUrl

I'm not sure what that would be in C#, but this is what it is in VB and it works a treat

我不确定在C#中会有什么,但这就是它在VB中的作用,它可以解决问题

#6


try something like this:

尝试这样的事情:

            if (Request.HttpMethod == "GET" && shouldChangeUrl)
            {
                urlRedirect = "REAL-URL-HERE";

                _postBackUrl = urlRedirect;
                Context.RewritePath(urlRedirect);
            }
            else
                //If Post Back (Request.HttpMethod="POST")
                Context.RewritePath(_postBackUrl);

So, you save the real URL for the postback in a variable (here: _postBackUrl) when rewriting the url and then use it only when postback.

因此,在重写url时,将回发的实际URL保存在变量(此处为:_postBackUrl)中,然后仅在回发时使用它。

#7


The problem is within the 404 handling. Your form is posting to a non-exising page, ASP.NET redirects the request to the 404 page and so it loses all the postback data.

问题在于404处理。您的表单发布到一个不存在的页面,ASP.NET将请求重定向到404页面,因此它丢失了所有回发数据。

The only solution is to set the form's action attribute to the existing page, so users will see the index.aspx?user=john when they submit the form. For SEO this would not be a problem, since crawlers don't issue posts and therefore do not see the ugly address.

唯一的解决方案是将表单的action属性设置为现有页面,这样用户在提交表单时将看到index.aspx?user = john。对于SEO这不会是一个问题,因为爬虫不发布帖子,因此看不到丑陋的地址。

#1


form1.Action = Request.RawUrl

in combination with

与...结合

HttpContext.Current.RewritePath("/Default.aspx", true); 

works very well for me.

对我来说效果很好。

setting the form Action attribute was the piece i was missing...

设置表单Action属性是我缺少的那个...

Thanks for the solution!!!

谢谢你的解决方案!

#2


Scott Guthrie covers different ways of doing this here without IIS access:

Scott Guthrie在没有IIS访问的情况下介绍了不同的方法:

http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx

Personally, I've created HTTPModules in the past and it's pretty easy to put together.

就个人而言,我过去创建了HTTPModules,它很容易组合在一起。

#3


form1.Action = Request.RawUrl is also how it is written in C# put it in the page load method

form1.Action = Request.RawUrl也是如何用C#编写的把它放在页面加载方法中

#4


I would start by installing Live Http Headers and see whats going on with the Http requests.

我将首先安装Live Http Headers并查看Http请求的最新情况。

Ahh here in that article it explains it, looks like the action attribute of the form tag is wrong:

啊,在那篇文章中它解释了它,看起来像form标签的action属性是错误的:

One gotcha that people often run into when using ASP.NET and Url-Rewriting has to-do with handling postback scenarios. Specifically, when you place a <form runat="server"> control on a page, ASP.NET will automatically by default output the "action" attribute of the markup to point back to the page it is on. The problem when using URL-Rewriting is that the URL that the control renders is not the original URL of the request (for example: /products/books), but rather the re-written one (for example: /products.aspx?category=books). This means that when you do a postback to the server, the URL will not be your nice clean one.

人们经常在使用ASP.NET和Url-Rewriting时遇到的问题与处理回发场景有关。具体来说,当您在页面上放置

控件时,ASP.NET将自动默认输出标记的“action”属性以指向它所在的页面。使用URL重写时的问题是控件呈现的URL不是请求的原始URL(例如:/ products / books),而是重写的URL(例如:/products.aspx?category =书籍)。这意味着当您对服务器进行回发时,URL将不是您干净利落的URL。

With ASP.NET 1.0 and 1.1, people often resorted to sub-classing the <form> control and created their own control that correctly output the action to use. While this works, it ends up being a little messy - since it means you have to update all of your pages to use this alternate form control, and it can sometimes have problems with the Visual Studio WYSIWYG designer.

在ASP.NET 1.0和1.1中,人们经常使用

控件进行子类化并创建自己的控件来正确输出要使用的操作。虽然这有效,但最终会有点混乱 - 因为这意味着您必须更新所有页面以使用此备用表单控件,并且有时可能会遇到Visual Studio WYSIWYG设计器的问题。

The good news is that with ASP.NET 2.0, there is a cleaner trick that you can use to rewrite the "action" attribute on the <form> control. Specifically, you can take advantage of the new ASP.NET 2.0 Control Adapter extensibility architecture to customize the rendering of the <form> control, and override its "action" attribute value with a value you provide. This doesn't require you to change any code in your .aspx pages. Instead, just add a .browser file to your /app_browsers folder that registers a Control Adapter class to use to output the new "action" attribute...

好消息是,使用ASP.NET 2.0,您可以使用更清晰的技巧重写

控件上的“action”属性。具体来说,您可以利用新的ASP.NET 2.0控件适配器可扩展性体系结构来自定义控件的呈现,并使用您提供的值覆盖其“action”属性值。这不需要您更改.aspx页面中的任何代码。相反,只需将.browser文件添加到/ app_browsers文件夹中,该文件夹注册一个Control Adapter类,用于输出新的“action”属性...

#5


You could just use the below instead:

您可以使用以下代替:

form1.Action = Request.RawUrl

form1.Action = Request.RawUrl

I'm not sure what that would be in C#, but this is what it is in VB and it works a treat

我不确定在C#中会有什么,但这就是它在VB中的作用,它可以解决问题

#6


try something like this:

尝试这样的事情:

            if (Request.HttpMethod == "GET" && shouldChangeUrl)
            {
                urlRedirect = "REAL-URL-HERE";

                _postBackUrl = urlRedirect;
                Context.RewritePath(urlRedirect);
            }
            else
                //If Post Back (Request.HttpMethod="POST")
                Context.RewritePath(_postBackUrl);

So, you save the real URL for the postback in a variable (here: _postBackUrl) when rewriting the url and then use it only when postback.

因此,在重写url时,将回发的实际URL保存在变量(此处为:_postBackUrl)中,然后仅在回发时使用它。

#7


The problem is within the 404 handling. Your form is posting to a non-exising page, ASP.NET redirects the request to the 404 page and so it loses all the postback data.

问题在于404处理。您的表单发布到一个不存在的页面,ASP.NET将请求重定向到404页面,因此它丢失了所有回发数据。

The only solution is to set the form's action attribute to the existing page, so users will see the index.aspx?user=john when they submit the form. For SEO this would not be a problem, since crawlers don't issue posts and therefore do not see the ugly address.

唯一的解决方案是将表单的action属性设置为现有页面,这样用户在提交表单时将看到index.aspx?user = john。对于SEO这不会是一个问题,因为爬虫不发布帖子,因此看不到丑陋的地址。