IIS 6: How to handle a space (%20) after .aspx - asp.net

Occasionally, my IIS 6 server will receive a request which contains a space after ".aspx", like:
http://www.foo.com/mypage.aspx%20?param=value
The "%20" immediately following ".aspx" causes the server to result in a "404 Page Not Found".
Is there a way to configure IIS to accept ".aspx%20" and process the page as if the "%20" didn't exist?
I looked at the "Home Directory" / "Configuration" in the properties of the site in IIS Manager and I added an entry for ".aspx%20" but that didn't work. Any other suggestions are appreciated.

+1 for the custom HttpModule (as Frédéric Hamidi suggested). It's a clean, modular solution and may help you rewrite other URLS, should you need to do so.
Your OnBeginRequest (referring to the link Frédéric provided) might look more or less like this:
private void OnBeginRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
string url = context.Request.RawUrl;
context.RewritePath(url.Replace(".aspx%20",".aspx"), false);
}

You might want to consider writing an HTTP module to remove the trailing space from the URL.

Override the 404 page in your web.config and handle the situation you described in code.

Related

How to auto-redirect URLs by patterns in ASP.NET / IIS 6?

I thought it should be a simple straight-forward matter but after struggling with it for too much time I'm gonna have to seek for help.
What I need is to redirect all requests for my web application that match the following pattern - "^(http://[^/]+/blogs/[^/.]+)/?$" to the path of "$1/Default.aspx".
(Using English rather than Regex: http://myapp/blogs/randomdirthatdoesntexist -> http://myapp/blogs/randomdirthatdoesntexist/default.aspx)
The sub-directories in "blogs" do not physically exist, instead a 3rd party product deals with the requests to randomdir/Default.aspx", but when you go to "randomdir/" you get 404 not found, which is what I'm trying to fix.
I tried to use global.asax and also HttpHandler, but I couldn't get either of them to fire up on the requests to those 404 paths.
So, in short, what should I do to redirect paths of non-existing directories?
Thanks.
I accomplished something similar to this by setting the Error Page for 404s in IIS to a page you create. This page is able to access the page which is being requested, and perform some additional logic. So the 404 for randomdirthatdoesntexist/ still happens, but the 404 handler notices this and redirects to randomdirthatdoesntexist/default.aspx.
I dug out my old code and tweaked it a little to do what you need in an over-simplified fashion, but I don't have IIS6 anywhere to test:
protected void Page_Load(object sender, EventArgs e)
{
String sQueryString = Request.RawUrl.Substring(Request.FilePath.Length);
Regex rx = new Regex(#"^\?(?<errorcode>\d+);(?<args>.*)$", RegexOptions.ExplicitCapture | RegexOptions.Compiled);
Match m = rx.Match(sQueryString);
if (m.Success)
{
if (m.Groups["errorcode"].Value == "404")
{
String sArgs = m.Groups["args"].Value;
Uri requestedUri = new Uri(sArgs);
// You can now check the value of uri and perform redirection...
if (requestedUri.ToString().EndsWith("/"))
{
Response.Redirect(requestedUri + "Default.aspx")
}
}
}
Response.StatusCode = 404;
}
Use a Custom HttpModule, or Http Handler, which sits in early enough in the Http Request pipeline to direct your requests appropriately before any possible 404 response is determined.
See my own SO Q&A; Server.Transfer or Server.RewritePath for more details.

IE errors on file download through .ashx file with caching turned off

I have a simple 'file download' generic handler which sets the response contenttype and headers before sending the file through the same response.
I also have Response.Cache.SetCacheability(HttpCacheability.server) set in the global.asax.
As I have noticed from various sources, Internet Explorer doesn't like this no-cache setting and gives an error when trying to download the file (requested site unavailable or cannot be found).
I thought maybe I could override this setting in the .ashx page, so I alter the response's cacheability setting to public. This did not solve the issue... removing the line from global.asax does solve the problem but obviously affects the whole site.
Is there a way of setting the cachability just for my generic handler?
Cheers :D
Can you just check whether the request is made to your generic handler and provide the appropriate cache settings depending on the result ? Something like this:
public void Application_OnPreRequestHandlerExecute(object sender, EventArgs e)
{
if (!HttpContext.Current.Request.Url.AbsolutePath.EndsWith("MyHandler.asxh", StringComparison.InvariantCultureIgnoreCase))
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Server);
}
}

How to send status code "500" for generic error page in IIS?

I am using a generic error page using ASP.NET's <customErrors> directive.
<customErrors mode="On" defaultRedirect="500.html" redirectMode="ResponseRewrite">
</customErrors>
Problem - when an error occurs, this page does not return HTTP status "500". It comes as 200. So link checkers and spiders do not see that there is any problem.
How can I send the 500 HTTP status along with the static 500.html page?
Requirements:
I must use redirectMode="ResponseRewrite"
I can't use a dynamic page, only static .html.
The MSDN documentation for the customErrors element states that it is implemented by System.Web.Configuration.CustomErrorsSection. If we use Red Gate's .NET Reflector to analyze that class, we can see where that setting is used in the Framework.
It is used by System.Web.UI.Page.HandleError and System.Web.HttpResponse.ReportRuntimeError.
Both of these end up calling System.Web.HttpResponse.RedirectToErrorPage. (The name of this method is confusing: it is important to note that RedirectToErrorPage takes the redirectMode setting as a parameter, so it is called even if you are using ResponseRewrite and no redirection actually happens.)
The relevant part of the RedirectToErrorPage method is:
if (redirectMode == CustomErrorsRedirectMode.ResponseRewrite)
{
this.Context.Server.Execute(url);
}
There doesn't appear to be any way to set the response code in the error handling: at the end of the day it's just a plain Server.Execute. It therefore seems unavoidable that you would need to write code to achieve the HTTP response you want.
Can you re-examine why you want to use a plain .html file? This seems a sensible choice for error handling, because you don't want to go through all the overhead of a .aspx page when that might cause another error to occur.
But perhaps there is some middle ground which will be just as robust as a .html file?
For example, you could make a precompiled HttpHandler, register it to the URL /500.error, and then make 500.error your defaultRedirect page. (This would be similar to how ScriptResource.axd works.) If you precompile your module into a DLL (as opposed to on-the-fly compilation from a plain old .axd file), you may find it is just as robust in the face of error conditions. If you encounter an error where not even this will work, then a static .html file probably won't work either -- keep in mind that the customErrors directive still relies on .NET running under the hood, and still uses the StaticFileHandler to serve your .html file.
Alternatively you could consider a reverse proxy in front of your IIS application which would serve a friendly 500 page even in the face of catastrophic failure of the application pool. This would be more work to set up, but would be even more robust than customErrors, e.g. if your web.config becomes corrupted, even customErrors won't work.
In your gllobal.asax file add the following code
protected void Application_EndRequest(object sender, EventArgs e)
{
if (Request.Url.AbsolutePath.EndsWith("500.html"))
Response.StatusCode = 500;
}
OK, I have a solution, the only way I can get this to work is by bypassing the custom errors section in the web configuration file.
So, an example default.aspx
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
throw new Exception("boom");
}
}
Then in the global.asax file:
protected void Application_Error(object sender, EventArgs e)
{
// Clear the error to take control of process
Server.ClearError();
Response.WriteFile(Server.MapPath("500.html"));
Response.StatusCode = 500;
Response.StatusDescription = "Internal Server Error";
}
You can probably write a better handling mechanism for the 500.html part - I think this should do what you are trying to achieve.
Only tested with VS Cassini web server, however I see no reason why this shouldn't work in iis6.
Try configuring your custom errors section like this:
<customErrors mode="On" redirectMode="ResponseRewrite">
<error statusCode="500" redirect="500.aspx">
</customErrors>
In your 500.aspx file, change the response code in the page_load;
Response.StatusCode = 500;
Response.StatusDescription = "Internal Server Error";
This could be done with an isapi filter. It would have to be written in c, but it can modify the response status for the .html request so that the browser gets a 500 with you custom html page.
If you insist on changing the core HTTP signaling then you either have to give in on some demands or be prepared to write your own web server. Yes you have to run IIS7 integrated AppPool and you still may have to accept redirection to and active page since you are trying to fake that your server is down and server is not designed to fake suicide. So if it gives you one slim way to do it, your options are to either say thanks or develop your own, non-HTTP compliant server which will scramble response codes at will.

How to write redirect application in asp.net?

I need to move all requests from one domain to another. I want to change part of URL, like subdomain.olddomain/url -> subdomain.newdomain/url.
I was sure that this is piece of cake and wrote Application_Begin request as:
void Application_BeginRequest(object sender, EventArgs e)
{
string url = Request.Url.ToString().ToLower();
string from = ConfigurationSettings.AppSettings["from"];
if (url.IndexOf(from) >= 0)
{
url = url.Replace(from, ConfigurationSettings.AppSettings["to"]);
Response.Redirect(url);
}
else
{
if (url.IndexOf("error.aspx") < 0)
{
Response.Redirect("Error.aspx?url=" + Server.UrlEncode(url));
}
}
}
So far, I forget, that BeginRequest started only when file physically exist.
Any ideas, how I can make such redirect in asp.net without creating hundreds of old pages?
Not 100% sure, but I think if you uncheck the Check that file exists option in IIS, it should work. How you do this depends on the IIS version.
I would recommend using a tool like ISAPIRewrite [http://www.isapirewrite.com/] to manage this for IIS 6, or the built in URL Rewriting for IIS7.
No reason to reinvent the wheel...
I believe you can specify an ASPX to run on 404 errors. That page can perform the redirect.
I would recommend doing this on the DNS level. I would redirect with a permanent 301 redirect to ensure that your search engine rankings are not affected.

Problem with a URL that ends with %20

I have a big problem. There are devices in live that send the URL "/updates ". It's a typo of the developer for those devices. In the server logs, it looks like "/updates+".
I have a ManageURL rewriting module that handles all requests without extension. But this request causes an HttpException:
System.Web.HttpException:
System.Web.HttpException
at System.Web.Util.FileUtil.CheckSuspiciousPhysicalPath(String physicalPath)
at System.Web.HttpContext.ValidatePath()
at System.Web.HttpApplication.ValidatePathExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
As I see in the logs, the URL rewriting module does not even get this URL, so I cannot fix it there.
Is there a way to handle those URLs with ASP.NET?
Ok, this is an old thread, but I like to add a workable solution that works for all ASP.NET versions. Have a look at this answer in a related thread. It basically comes down to registering to the event PreSendRequestHeaders in global.asax.cs.
Alternatively, when on ASP.NET 4.0 or higher, use <httpRuntime relaxedUrlToFileSystemMapping="true" /> in web.config.
According to some, this is in System.Web.dll:
internal static void CheckSuspiciousPhysicalPath(string physicalPath)
{
if (((physicalPath != null) && (physicalPath.Length > 0))
&& (Path.GetFullPath(physicalPath) != physicalPath))
{
throw new HttpException(0x194, "");
}
}
I guess you cannot change that, but can't one disable it in the IIS settings? Of course, that would also disable all other checks... :-(
Or write some ISAPI filter that runs before the above code? Writing your own module is said to be easy, according to Handle URI hacking gracefully in ASP.NET.
Or, create your own error page. In this page (like suggested in the URI hacking link above) search for specific text in exception.TargetSite.Name, such as CheckSuspiciousPhysicalPath and if found (or simply always) look at current.Request.RawUrl or something like that, clear the error and redirect to a repaired URL?
you could run a URL-rewriting ISAPI, like IIRF.
If you have access to code why not just check for '+' at the end and remove it?

Resources