Monday, March 26, 2012

Wildcard Extensions, RewritePath and /jsdebug

What we have here is not an unusual situation, but not a common one.

We are using a wildcard extension mapping ".*" mapped to the asp.net (2.0) isapi library. We're doing this so that we can do UrlRewriting without using a seperate ISAPI extension and so that we can handle url rewrites on directories and configure the rewrites using the website's local web.config.

We have sections for exceptions on file extensions and directories, and overall this works really well... until we have to implement asp.net ajax.

Because asp.net ajax's ScriptManager defines the script in html as src="http://pics.10026.com/?src=ws/WebService.asmx/jsdebug" IIS sends this request to ASP.NET, which then looks for that directory path, and naturally, it doesnt exist.

So it throws a nasty ASP.NET 404 error when attempting to viewhttp://siteurl/ws/WebService/jsdebug.

I'm going to go out on a limb here and assume that whatever mechanism the asp.net ajax library is using to generate this javascript is being interrupted by all requests coming to the aspnet_isapi library. When I disable the wildcard extension mapping, everything works as it should.

ASP.NET AJAX Developers! How can I work around this limitation, using our current setup?

Hi,

I fail to reproduce the issue. Can you show me your code?


I am also using wildcard extension and UrlRewriting and I have no problem with that.

Maybe this is due to the fact that I added this line to my web.config (in order to solve another problem):


<add verb="*" path="*.js" type="System.Web.StaticFileHandler"/>

this must be placed in the "system.web" then "httpHandlers" section.


I'm experiencing the same exact problem. In fact, this problem even occurs when UrlRewriting.Net is disabled. I'm currently running ASP.NET 2.0 on Windows 2000 with IIS 5.0.

When I define the wildcard extension mapping, ScriptService URLs (e.g. xxxxx.asmx/js, xxxxx.asmx/jsdebug, and xxxxx.asmx/MethodName) all fail to work.

However, when I remove the wildcard mapping, everything works again.

One interesting I noticed is the way how IIS handle urls like "xxxxx.asmx/js" under the "no wildcard extension mapping" default IIS configuration.

For a URL like "xxxxx.asmx/js", I had expected it to fail under the default configuration since it should technically treat the URL as an extension-less url. Instead, it seems like IIS progressively traverse the path nodes and check to see if a node in the path resolves to an actual file. And if it does, it changes the requested path from "/xxxxx.asmx/js" to "/xxxxx.asmx" and stuffs the "/js" part as the "PathInfo" request header. (http://msdn2.microsoft.com/en-us/library/system.web.httprequest.pathinfo.aspx)

It seems like when wildcard extension mapping is turned on, IIS disables that behavior and forwards the request to ASP.net without parsing the requested path.

Does this make sense?

-David


I figured out why.

This misbehavior can be reproduced on IIS 5.0 (Windows 2000) and IIS 5.1 (Windows XP Pro). It does not effect VS's development server nor IIS 6.0.

When IIS 5.x sees a URL like this "/webservices/helloworld.asmx/js", it splits them into token and iterates through them from left to right. For each token, it checks to see if it ends as a string that matches an extension mapping. As soon as it finds it, it stops. At this point, before IIS forward the request to ASP.Net's ISAPI extension, it takes that finding and creates two server variables: URL and PATH_INFO.

For example, the following URL:

"/webservices/helloworld.asmx/js"

would cause IIS to define the following server variables:

SERVER_VARIABLE["URL"]: "/webservices/helloworld.asmx"
SERVER_VARIABLE["PATH_INFO"]: "/webservices/helloworld.asmx/js"

Similarly, a URL like this:

"/nonexistent.aspx/helloworld.asmx/js"

would cause IIS to define the following server variables:

SERVER_VARIABLE["URL"]: "/nonexistent.aspx"
SERVER_VARIABLE["PATH_INFO"]: "/nonexistent.aspx/helloworld.asmx/js"

When you turn on IIS 5.x wildcard extension mapping, this logic never gets executed. Instead, IIS defines the URL server variable the same way it defines PATH_INFO (i.e. nothing is stripped out).

ASP.Net does not like this. Without URL rewriting, ASP.Net doesn't know how to handle the request "/webservices/helloworld.asmx/js". Because of this, ASP.Net forwards the request to the FileNotFound http handler which displays the 404 error page we see.

Again, this only applies to IIS 5.x and not IIS 6.0. IIS 6.0 seems to have reworked this logic in the expected way.

To solve this problem, create a file called IIS5XWildCardExtensionFix.cs and place it in your App_Code folder:

using System;using System.Web;public class IIS5XWildCardExtensionFix : IHttpModule{public IIS5XWildCardExtensionFix() { }public void Dispose() { }public void Init(HttpApplication context) { context.BeginRequest +=new EventHandler(OnBeginRequest); }private void OnBeginRequest(object sender, EventArgs e) { HttpApplication app = senderas HttpApplication; HttpContext context = app.Context;string path = context.Request.Path;int asmx = path.IndexOf(".asmx/", StringComparison.OrdinalIgnoreCase);if (asmx >= 0) context.RewritePath( path.Substring(0, asmx + 5), path.Substring(asmx + 5), context.Request.QueryString.ToString()); }}


Add the following line to in your web.config file in the HttpModules tag:

<add name="IIS5XWildCardExtensionFix" type="IIS5XWildCardExtensionFix" />

This code inserts the missing logic using ASP.Net's HTTP Module framework.

This code is derived from djMax'spost.

-David


Fantastic work. I really appreciate you diving into this logic and figuring out the problem. We are, in fact, running XP Pro on most of our development machines.

I'll be giving this fix a shot next week Monday and will report back with my findings.


I tried this solution without luck :\ Will create a new thread with the info.

Basically, removing the wildcard extension mapping fixes the issue, but we need to retain that mapping, so since adding it we are getting the 'Sys is undefined' error indicating the client is not receiving the .js file.


You don't have to remove the wildcard extension mapping. In fact, this code is meant to address the issue introduced by defining the wildcard extension mapping.


Here is the .vb we used, and included the tag in our web.config

Imports System
Imports System.Web
Imports Microsoft.VisualBasic

PublicClass IIS5XWildCardExtensionFix
Implements IHttpModule

PublicSubNew()
EndSub

PublicSub Dispose()Implements System.Web.IHttpModule.Dispose
EndSub

PublicSub Init(ByVal contextAs System.Web.HttpApplication)Implements System.Web.IHttpModule.Init
AddHandler context.BeginRequest,AddressOf OnBeginRequest
EndSub

PrivateSub OnBeginRequest(ByVal senderAsObject,ByVal eAs EventArgs)
Dim appAs HttpApplication =CType(sender, HttpApplication)
Dim contextAs HttpContext = app.Context
Dim pathAsString = context.Request.Path
Dim asmxAsInteger = path.IndexOf(".asmx/", StringComparison.OrdinalIgnoreCase)
If (asmx >= 0)Then
context.RewritePath(path.Substring(0, asmx + 5), path.Substring(asmx + 5), context.Request.QueryString.ToString())
EndIf
EndSub

EndClass


understood, thank you. We aren't able to remove the wildcard mapping which is why I am attempting this workaround. So far no luck, but thank you for your help thus far.


Are you guys stripping out ".asmx" during the URL rewriting process?

This will not work:http://yoursite.com/ws/WebService/jsdebug
This will work:http://yoursite.com/ws/WebService.asmx/jsdebug

What's the src attribute in your aspx page's script tag?


we are not actually rewriting urls, we are securing documents in particular directories using forms authentication. In order for this to work for documents other than aspx files, we needed to add the wildcard application mapping. I tried specifically granting access the ScriptResource.axd and WebResource.axd files in the web.config per other posts suggestions but nothing has yet worked. I can provide url if it's allowed, or email it...


buddydvd2:

I'm experiencing the same exact problem. In fact, this problem even occurs when UrlRewriting.Net is disabled. I'm currently running ASP.NET 2.0 on Windows 2000 with IIS 5.0.

When I define the wildcard extension mapping, ScriptService URLs (e.g. xxxxx.asmx/js, xxxxx.asmx/jsdebug, and xxxxx.asmx/MethodName) all fail to work.

However, when I remove the wildcard mapping, everything works again.

One interesting I noticed is the way how IIS handle urls like "xxxxx.asmx/js" under the "no wildcard extension mapping" default IIS configuration.

For a URL like "xxxxx.asmx/js", I had expected it to fail under the default configuration since it should technically treat the URL as an extension-less url. Instead, it seems like IIS progressively traverse the path nodes and check to see if a node in the path resolves to an actual file. And if it does, it changes the requested path from "/xxxxx.asmx/js" to "/xxxxx.asmx" and stuffs the "/js" part as the "PathInfo" request header. (http://msdn2.microsoft.com/en-us/library/system.web.httprequest.pathinfo.aspx)

It seems like when wildcard extension mapping is turned on, IIS disables that behavior and forwards the request to ASP.net without parsing the requested path.

Buddydvd2. I think I have very similar problem you are experiencing, but littel different. Enabling IIS Wildcard makes Ajax Toolkit Slides control not working. I have posted the problem here, please take a look:http://forums.asp.net/t/1129701.aspx

I have tried to apply your logic to axd files, but that did not help

Please help anybody


buddydvd2:

Are you guys stripping out ".asmx" during the URL rewriting process?

This will not work:http://yoursite.com/ws/WebService/jsdebug
This will work:http://yoursite.com/ws/WebService.asmx/jsdebug

What's the src attribute in your aspx page's script tag?

This is the source I have on my page for Slides Control in Ajax Toolkit:

<script src="http://pics.10026.com/?src=/Ajax/WebResource.axd?d=BP8NIIT9ZyjyxNDvn4jUWQ2&t=633144946505000000" type="text/javascript"></script>


<script src="http://pics.10026.com/?src=/Ajax/ScriptResource.axd?d=OjqU9cYdOHT3Lc3mu9VgciBgwPmofPtVg5ti2UT6BGvFCwWflQSi8HHOJb5SHbTBOpqi8xLjNGpMCKeePlMrcNXw15AoxwpCVLq3SBhMer81&t=633144934480000000" type="text/javascript"></script>

Please help


Hi Rafal,

Try your solution on a machine with IIS 6 installed. The error you're getting is most likely caused by IIS 5.x. The error response you got, "HTTP verb POST not allowed", says that the request didn't even get routed to ASP.Net's ISAPI extension module yet.

Also, make sure you select "All verbs" in the extension mapping dialog for your wildcard mapping (i.e "*.").

Hope that helps,
Good luck.

-David

No comments:

Post a Comment