29

我有一个包含 Web API 的 ASP.NET MVC 4 网站。该站点是在 Windows 8 上使用 Visual Studio 2012 和 .NET 4.5 开发和测试的,IIS Express 作为 Web 服务器。在这个开发环境中一切正常。

现在它部署在带有 IIS 7.5 的 Windows 2008 R2 (SP1) 服务器上。.NET 4.0 和 4.5 已安装。应用程序池在集成管道模式下使用 .NET 4.0 运行。

在这个生产环境中,MVC 网站工作,Web API 不工作。对于每个请求,无论是 GET 还是 POST,我都会收到 404 错误。如果我只是在浏览器中输入一个 Web API Url(在服务器上本地打开 IE 9)来运行一个 GET 请求,我会得到一个 404 页面。如果我从 Web API 客户端应用程序发出 POST 请求,我也会收到 404 和以下消息:

未找到与请求 URI 匹配的 HTTP 资源

我还使用 MVC 4 和 Web API 创建了一个测试网站,并将其部署在同一台服务器上,并且 Web API 可以正常工作。Web API 和 MVC 程序集在两个项目中具有相同的版本号。

此外,我已将Web API 路由调试器添加到应用程序中。如果我使用像http://myserver/api/order/12我这样的有效路线,则会得到以下结果:

路由调试器

对我来说,这意味着Api/{Controller}/{Id}已找到正确的路由模板并将其正确解析为控制器OrderId=12. 控制器(派生自ApiController)存在于所有 MVC 控制器所在的 Web 程序集中。

但是,我不知道状态000可能意味着什么以及为什么没有显示“路线选择”部分(即使程序集不包含单个ApiController,通常也是这种情况,请参阅上面链接页面上的屏幕截图)。不知何故,看起来好像没有ApiController找到,甚至没有搜索到,或者搜索默默地失败了。

IIS 日志文件没有显示任何有用的信息。更改各种应用程序池设置并使用相同的应用程序池进行测试和实际应用程序并没有帮助。

我目前正在从应用程序中删除“功能”、配置设置、第三方程序集等,最终将其缩小到测试应用程序的小尺寸,并希望它在某个时候开始工作。

有人知道问题可能是什么吗?此外,非常欢迎任何可能找到原因的调试或日志记录想法。

编辑

感谢 Darrel Miller 在下面评论中的提示,我已经集成了 Tracing for ASP.NET Web Api

对于 (GET) 请求 URL http://myserver/api/order/12,我得到以下信息:

  • 在开发环境中,成功(简称):

留言:http://localhost:50020/api/order/12; 类别:System.Web.Http.Request

控制器选择和实例化...

运算符:DefaultHttpControllerSelector;操作:选择控制器;消息:Route="controller:order,id:12"; 类别:System.Web.Http.Controllers

运算符:DefaultHttpControllerSelector;操作:选择控制器;消息:订单;类别:System.Web.Http.Controllers

运算符:HttpControllerDescriptor;操作:创建控制器;信息: ; 类别:System.Web.Http.Controllers

运算符:DefaultHttpControllerActivator;操作:创建;信息: ; 类别:System.Web.Http.Controllers

运算符:DefaultHttpControllerActivator;操作:创建;消息:MyApplication.ApiControllers.OrderController;类别:System.Web.Http.Controllers

动作选择、参数绑定和动作调用如下...

结果的内容协商和格式化...

运算符:DefaultContentNegotiator;操作:协商;消息:Typ = "String" ... 更多

处理控制器...

操作员:订单控制器;操作:处置;信息: ; 类别:System.Web.Http.Controllers

  • 在生产环境中,不成功(简称):

留言:http://myserver/api/order/12; 类别:System.Web.Http.Request

运算符:DefaultHttpControllerSelector;操作:选择控制器;消息:Route="controller:order,id:12"; 类别:System.Web.Http.Controllers

控制器激活、动作选择、参数绑定、动作调用的整个部分都丢失了,它立即遵循错误消息的内容协商和格式化

运算符:DefaultContentNegotiator;操作:协商;消息:Type = "HttpError" ...更多

4

3 回答 3

23

感谢Kiran Challa 的评论和来自这个答案的源代码,我能够弄清楚ReportViewer 11 assembly生产服务器上缺少一个程序集(用于 SQL Server Reporting Services)。

尽管ApiController此程序集中没有,但它似乎导致程序集中的控制器(在本例中为我的 Web 项目的程序集)正在引用缺少的程序集。

显然,此行为与Web APIDefaultHttpControllerTypeResolver源中的这段代码有关:

List<Type> result = new List<Type>();

// Go through all assemblies referenced by the application
// and search for types matching a predicate
ICollection<Assembly> assemblies = assembliesResolver.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
    Type[] exportedTypes = null;
    if (assembly == null || assembly.IsDynamic)
    {
        // can't call GetExportedTypes on a dynamic assembly
        continue;
    }

    try
    {
        exportedTypes = assembly.GetExportedTypes();
    }
    catch (ReflectionTypeLoadException ex)
    {
        exportedTypes = ex.Types;
    }
    catch
    {
        // We deliberately ignore all exceptions when building the cache. If 
        // a controller type is not found then we will respond later with a 404.
        // However, until then we don't know whether an exception at all will
        // have an impact on finding a controller.
        continue;
    }

    if (exportedTypes != null)
    {
        result.AddRange(exportedTypes.Where(x => IsControllerTypePredicate(x)));
    }
}

我不知道它是否必须这样,并且我不太相信代码中的注释,但是这个catch ... continue块对可能的问题相当沉默,我花了很多时间和挫折才找到它。我什至知道ReportViewer尚未安装。我尝试安装它和依赖程序集,但它被服务器上另一个正在运行的进程阻止,所以我决定推迟安装,直到我可以联系管理员并首先专注于 MVC 和 WebAPI 测试 - 大错误!如果没有 Kiran 的调试代码片段,我从未想过 a 的存在ReportViewer.dll可能与控制器类型解析有关。

在我看来,对于像我这样对 Web API 的内部工作没有更深入了解的普通开发人员来说,还有改进的空间。

安装后丢失ReportViewer.dll的问题消失了。

以下是关于可能具有相同原因的相同症状的问题:

编辑

我已发出对 CodePlex 的改进请求:

http://aspnetwebstack.codeplex.com/workitem/1075

编辑 2(2013 年 8 月 11 日)

该问题已针对 WebAPI v5.0 RC 进行了修复。有关详细信息,请参阅上面指向工作项及其评论部分的链接。

于 2013-05-29T22:54:43.533 回答
6

然而,这个答案中的大量资源,我得到了一个 404,结果证明这是一个非常愚蠢的原因:

  1. 我为我的 API 项目创建了一个 WiX 安装程序
  2. 将其安装在测试 VM(虚拟机)上
  3. 请求 API 应提供的 URI
  4. 砰!404:(

事实证明,我错过了将Global.asax打包和部署到部署中虚拟目录的根目录。为了像我这样的傻瓜的利益,在这里添加这个:)

于 2013-09-17T12:54:41.637 回答
0

我在远程服务器上遇到了同样的问题,但是当我在本地主机上执行时工作正常。

我的解决方案是:

<system.webServer>
    <modules>
        <remove name="UrlRoutingModule-4.0" />
        <add name="UrlRoutingModule-4.0" 
            type="System.Web.Routing.UrlRoutingModule" preCondition="" /> 
    </modules>
</system.webServer>

我希望,这对你有用。

于 2016-06-03T16:08:10.520 回答