Due to various engineering requirements, I need to develop a new ASP.NET Web API application (named as BarApp) within the same Application domain of an existing application (named as FooApp).
I would like to configure an ASP.NET Web API application (BarApp) as a virtual directory under an existing ASP.NET MVC application (FooApp) on IIS 8.5. Though many many posts talked about how to configure a virtual directory, none of them work.
Here is the configuration snippet
<site name="FooApp" id="3" serverAutoStart="true">
<application path="/" applicationPool="FooApp">
<virtualDirectory path="/" physicalPath="E:\FooApp" />
<virtualDirectory path="/Bar" physicalPath="E:\BarApp" />
</application>
<bindings>
<binding protocol="https" bindingInformation="*:34566:" sslFlags="0" />
</bindings>
</site>
Here is the website structure:
-FooApp
|
|--Bin
|--View
|--Bar (as a virtual directory)
|
|--Bin
|--View
In the Foo App, I configured the routing: add an ingore route for all path with Bar
--RouteConfig.cs
namespace FooApp
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*path}", new { path = @"Bar\/(.*)" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
--WebApiConfig, keep the automatically generated one.
namespace FooApp
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
In the BarApp, the routing configure is modified as:
--RouteConfig.cs
namespace BarApp
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "Bar/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
--WebApiConfig
namespace BarApp
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "Bar/api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
However, the above configuration does not work, and the ignore route seems not taken into effect.
Failed to access page of Bar: https://mywebsite.test.com:4433/Bar/
HTTP Error 403.14 - Forbidden
The Web server is configured to not list the contents of this directory.
Failed to access Web API of Bar: https://mywebsite.test.com:4433/Bar/api/values HTTP Error 404.0 - Not Found The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
the Web API library is 2.2.1
To create a virtual directory with IIS Manager for an ASP.NET application. In IIS Manager, expand the local computer and the Sites folder. Right-click the site or folder where you want to create the virtual directory and then click Add Virtual Directory.
ASP.NET Web API can be used with MVC for any type of application. A web API can help you develop ASP.NET application via AJAX. Hence, web API makes it easier for the developers to build an ASP.NET application that is compatible with any browser and almost any device.
Right-click the Web site that you want (for example, Default Web Site), point to New, and then click Virtual Directory. On the Welcome to the Virtual Directory Creation Wizard page, click Next. On the Virtual Directory Alias page, type the alias that you want (for example, Sales), and then click Next.
I think the problem with your approach is trying to host an Asp.Net application inside a Virtual Directory. Rather, you must add a child Application:
Then modify the web.config of the root application to avoid configuration collisions:
Reference: Disable inheritance in child applications and validateIntegratedModeConfiguration and inheritInChildApplications clash.
This way, you will be able to access your child web api without modifying any c# code:
I haven't setup virtual application using configuration files (only through IIS and publish) but I believe the issue you are having is the understanding of how the route URL is mapped in a virtual application. For the following, let's assume your FooApp has a DNS set to fooapp (http://fooapp/
).
If you have a Bar virtual application under fooapp, the root of the Bar website will be http://fooapp/Bar
. If we look at your route definitions (MVC and WebApi):
// MVC Route
routes.MapRoute(
name: "Default",
url: "Bar/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
// WebApi Route
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "Bar/api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Both your routes are set to listen to a Bar
"directory" under the running application. If your WebApi application we published on its own (let's say on localhost), this would be http://localhost/Bar
. But you are actually under http://fooapp/Bar
and it will be capturing the request based on that root path which would be http://fooapp/Bar/Bar
(so http://fooapp/Bar/Bar/api/values
, etc..).
As far as ignore routes goes, if there is no controller handling a route on /Bar
in the FooApp
, the application will tell IIS that it doesn't know how to treat the request and IIS will then move to other Handlers (static file handlers, and so on). Let's take your request as an example (https://mywebsite.test.com:4433/Bar/
). Since it's under a virtual application, it will ask the Bar
application if it can handle a /
route. Since your route definitions in the Bar application only handles /Bar/{tokens}
, it will default to the static file handler (which in this case would be the directory browsing) and return a 403 due to configuration.
If you take your second example (https://mywebsite.test.com:4433/Bar/api/values
), it will ask the Bar application if it can handle /api/values
which it can't (remember, it can handle /Bar/api/values
, not /api/values
). Since your application can't, it will go back to the other handlers and nobody will be able to fulfill the request and return a 404.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With