在ASP.NET MVC应用程序下将ASP.NET Web API应用程序配置为虚拟目录

时间:2014-03-01 01:43:56

标签: asp.net-mvc asp.net-web-api virtual-directory

由于各种工程要求,我需要在现有应用程序的同一个应用程序域(名为FooApp)中开发一个新的ASP.NET Web API应用程序(名为BarApp)。

我想将ASP.NET Web API应用程序(BarApp)配置为IIS 8.5上现有ASP.NET MVC应用程序(FooApp)下的虚拟目录。尽管许多帖子都谈到了如何配置虚拟目录,但它们都不起作用。

以下是配置代码段

        <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>

以下是网站结构:

-FooApp
|
|--Bin
|--View
|--Bar (as a virtual directory)
    |
    |--Bin
    |--View   

在Foo App中,我配置了路由:为Bar

添加所有路径的ingore路由
--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,保留自动生成的。

 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 }
            );
          }
     }
}

在BarApp中,路由配置修改为:

--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 }
        );
      }
   }
}

但是,上述配置不起作用,忽略路由似乎没有生效 无法访问Bar的页面:https://mywebsite.test.com:4433/Bar/ HTTP错误403.14 - 禁止 Web服务器配置为不列出此目录的内容。

无法访问Bar的Web API:https://mywebsite.test.com:4433/Bar/api/values HTTP错误404.0 - 未找到 您要查找的资源已被删除,名称已更改或暂时不可用。

Web API库是2.2.1

3 个答案:

答案 0 :(得分:5)

我认为您的方法存在的问题是尝试在虚拟目录中托管Asp.Net应用程序。相反,您必须添加一个孩子应用

IIS - Add child application

然后修改根应用程序的web.config以避免配置冲突:

Avoid collisions in child's web.config

参考:Disable inheritance in child applicationsvalidateIntegratedModeConfiguration and inheritInChildApplications clash

这样,您就可以在不修改任何c#代码的情况下访问您的子web api:

Child web api

答案 1 :(得分:4)

我没有使用配置文件设置虚拟应用程序(仅通过IIS和发布),但我相信您遇到的问题是了解路由URL在虚拟应用程序中的映射方式。对于以下内容,我们假设您的FooApp将DNS设置为fooapp(http://fooapp/)。

如果您在fooapp下有一个Bar虚拟应用程序,则Bar网站的根目录将为http://fooapp/Bar。如果我们查看您的路由定义(MVC和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 }
);

您的路由都设置为在正在运行的应用程序下侦听Bar“目录”。如果我们自己发布的WebApi应用程序(比如localhost),那就是http://localhost/Bar。但是你实际上在http://fooapp/Bar下,它将根据该根路径捕获请求http://fooapp/Bar/Bar(所以http://fooapp/Bar/Bar/api/values等等。)。

就忽略路由而言,如果没有控制器处理/BarFooApp上的路由,应用程序将告诉IIS它不知道如何处理请求和IIS然后将移动到其他处理程序(静态文件处理程序,等等)。我们以您的请求为例(https://mywebsite.test.com:4433/Bar/)。由于它位于虚拟应用程序下,因此它将询问Bar应用程序是否可以处理/路由。由于Bar应用程序中的路由定义仅处理/Bar/{tokens},因此它将默认为静态文件处理程序(在本例中为目录浏览)并由于配置而返回403。

如果您采用第二个示例(https://mywebsite.test.com:4433/Bar/api/values),它会询问Bar应用程序是否可以处理它不能处理的/api/values(请记住,它可以处理/Bar/api/values,而不是/api/values)。由于您的应用程序不能,它将返回到其他处理程序,没有人能够满足请求并返回404。

答案 2 :(得分:0)

我遇到了同样的问题。解决方案很简单:在MVC RouteConfiguration中你需要到子虚拟应用程序的路由(如果你在foo下有条形,foo需要知道条形路由)。

对于酒吧应用程序,您需要Simon记录的路线!

亲切的问候

塔拉