It is common situation when site developed and tested on IIS web-site root, and deployed into Virtual Directory. Here I want to describe some tips to avoid such situations.
1. Do not use relative paths.
It is a first and biggest pain. Convert relative paths to absolute using:
VirtualPathUtility.ToAbsolute(virtualPath);2. Add trailing slash to default path.
When you use MVC, you can have an exception in your site map (I use MvcSiteMap provider) when you request your site without trailing slash. For example, this request may works fine:
http://siteroot/testvd/but this one cause an exception when you try to access SiteMap.CurrentNode:
http://siteroot/testvdWhy? Hmm... it is an interesting question, I saw such situations on IIS 5,6 configured to work with MVC. If not to go very deep in ASP.NET - because registered path in site map contains trailing slash, and there is no path without slash. It is standard behavior of ASP.NET. In WebForms (not MVC) site, when you try to access such path, IIS redirects you to path with trailing slash automatically. I think, since here IIS send all requests directly to ASP.NET (because of registered wildcard or .* extension used for MVC works fine), it can't redirect user to page with trailing slash.
To fix this you can add next code in your Global.asax.cs:
/// <summary> /// Starts each request /// </summary> protected void Application_BeginRequest() { if (Request.ApplicationPath == Request.Path) Context.RewritePath(VirtualPathUtility.AppendTrailingSlash(Request.ApplicationPath), true); }3. Testing site in VD using HttpSimulator, developed by Phil Haack, can cause unexpected result.
Here is pseudo-code that can cause incorrect results:
string path = string.Empty; using (new HttpSimulator("/TestVD").SimulateRequest()) { path = VirtualPathUtility.ToAbsolute("/images/Test.png"); } // expected result: path = "/TestVD/images/Test.png"; // actual result: path = "/TestVDimages/Test.png";To correct this you must change code of method SetHttpRuntimeInternals in HttpSimulator.cs (changed lines are highlighted):
void SetHttpRuntimeInternals() { // ... // set app virtual path property value string vpathTypeName = "System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; string appPath = VirtualPathUtility.AppendTrailingSlash(ApplicationPath); object virtualPath = ReflectionHelper.Instantiate(vpathTypeName, new Type[] { typeof(string) }, new object[] { appPath }); ReflectionHelper.SetPrivateInstanceFieldValue("_appDomainAppVPath", runtime, virtualPath); // ... }
Great!! Excactly what i was looking for :)
ReplyDeleteCool to hear that it helps to someone else, I'll try to keep posting such a things.
DeleteIs it possible to do the same for WebAPI application?
ReplyDeleteI have a web api application, in which I have few apis and also have an angular app which consumes those apis.
everything works fine on local but once I release it on another environment(with virtual path), url rewriting logic breaks.