"The resource cannot be found." error when there is a "dot" at the end of the url
I'm using ASP .NET MVC Beta and I get the HTTP 404 (The resource cannot be found) error when I use this url which has a "dot" at the end:
http://localhost:81/Title/Edit/Code1.
If I remove the dot at the end or the dot is somewhere in the middle I don't get the error.
I tried to debug but it I get the error from "System.Web.CachedPathData.GetConfigPathData(String configPath)" before ProcessRequest in MvcHandler.
Is "dot" not allowed at the end of a url? Or is there a way to fix the route definition to handle this url?
For an example: I have a table named Detail1 [Id(integer), Code(string), Description(string)] which has FK relationship with Master1 through it's Id column. Whenever I select a record of Master1, I also select it's Detail1 record to get it's Code field. In order to not to make this join everytime (since usually there isn't only one detail, there are more than one) I choose not to use Id column and I make Code PK of Detail1.
But when I get rid of Id and use Code as PK then my routes also start to work with Code field, like: Detail1\Edit\Code1
This Code can have anything in it or at the end, including DOT. There are cases where I can prohibit a DOT at the end but sometimes it's really meaningfull.
And I'have also seen this post that routes can be very flexible, so I didn't think mine is so weird.
So that's why I do something so non-standard. Any suggestions?
And also why it's so weird to have a DOT at the end of a url?
If you are using .NET 4.0, you can set this flag in the system.web section of your web.config and it will be allowed:
<httpRuntime relaxedUrlToFileSystemMapping="true" />
I've tested it and it works. Haack has an explanation of it.
This can be solved in a couple of ways in every ASP.NET version from 1.0 and up. I know it's two years after this thread has been created, but anyway, here it goes:
Cause
Creating your custom error handler, or configuring a custom page in IIS for redirecting the 404 will not work. The reason is that ASP.NET considers this URL dangerous. Internally in System.Web.Util.FileUtil
, ASP.NET calls a private method IsSuspiciousPhysicalPath
, which tries to map the path to a (virtual but legal) filename.
When the resulting legalized path is not equal to the original path, processing stops and the ASP.NET code returns a 404 (it doesn't ask IIS or the web.config for the custom 404, it returns one itself, which makes it so hard to do something about this).
Windows Explorer works the same way. Try to create a filename ending in one or more dots, i.e. test.txt.
. You will find that the resulting name is text.txt
.
Solution for ending URL in a dot in ASP.NET
The solution is simple (once you know it, it always is). Just before it sends out this 404, it will call Application_PreSendRequestHeaders
, a simple event that you can register to in Global.asax.cs
(or the VB equivalent). The following code will return a simple text to the browser, but a Redirect, or any other valid response is also possible.
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpResponse response = this.Context.Response;
HttpRequest request = this.Context.Request;
if (request.RawUrl.EndsWith("."))
{
response.ClearContent();
response.StatusCode = 200;
response.StatusDescription = "OK";
response.SuppressContent = false;
response.ContentType = "text/plain";
response.Write("You have dot at the end of the url, this is allowed, but not by ASP.NET, but I caught you!");
response.End();
}
}
Note: this code also works when "aspx" is not part of the URL. I.e., http://example.com/app/somepath. will call that event. Also note that some paths still won't work (ending with multiple dots, with a hash-tag, or a < -sign, for instance, causes a 400- Bad Request). Then again, it does work for ending on a quote, a space+slash, or multiple dots separated by spaces.
Well, in .NET 4.5 I fixed this problem by adding "/" to the end of the url.
So, in your case it would be "http://localhost:81/Title/Edit/Code1./". It was the only thing I did, I didn't have to add httpRuntime setting.
add this to handlers
<add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
path="api/*"
verb="*"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>