对 ASP.NET Web API 的所有请求都返回 404 错误 [英] All requests to ASP.NET Web API return 404 error

查看:25
本文介绍了对 ASP.NET Web API 的所有请求都返回 404 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 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 程序集在两者中具有相同的版本号项目.

此外,我添加了 .

对于 (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" ...更多

处置控制器...

操作员:OrderController;操作:处置;信息: ;类别: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" ... more

解决方案

感谢 Kiran Challa 的评论和来源来自 这个答案 的代码我能够弄清楚一个程序集(ReportViewer 11 程序集 forSQL Server Reporting Services)在生产服务器上丢失.

尽管此程序集中没有 ApiController ,但似乎导致程序集中的控制器 - 在本例中是我的 Web 项目的程序集 - 未找到引用丢失的程序集.

显然这种行为与 Web API 的 DefaultHttpControllerTypeResolver 来源:

List结果 = 新列表<类型>();//遍历应用程序引用的所有程序集//并搜索匹配谓词的类型ICollection<程序集>程序集 = assemblyResolver.GetAssemblies();foreach(程序集中的程序集){类型[]导出类型=空;if (assembly == null || assembly.IsDynamic){//不能在动态程序集上调用 GetExportedTypes继续;}尝试{exportTypes = assembly.GetExportedTypes();}catch (ReflectionTypeLoadException ex){exportTypes = ex.Types;}抓住{//我们在构建缓存时故意忽略所有异常.如果//未找到控制器类型,稍后我们将使用 404 进行响应.//然而,在那之前我们根本不知道异常是否会发生//对找到控制器有影响.继续;}if (exportedTypes != null){result.AddRange(exportedTypes.Where(x => IsControllerTypePredicate(x)));}}

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

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

安装缺少的ReportViewer.dll后,问题消失了.

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

编辑

我已发出改进 CodePlex 的请求:

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

编辑 2(2013 年 8 月 11 日)

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

I have an ASP.NET MVC 4 web site that includes Web API. The site is developed and tested with Visual Studio 2012 and .NET 4.5 on Windows 8 with IIS Express as web server. In this development environment everything works.

Now it is deployed on a Windows 2008 R2 (SP1) Server with IIS 7.5. .NET 4.0 and 4.5 are installed. The application pool is running with .NET 4.0 in integrated pipeline mode.

In this production environment the MVC web site works, Web API does not. For every request, no matter if GET or POST I get a 404 error. If I just enter a Web API Url in the browser (IE 9 opened locally on the server) to run a GET request I get a 404 page. If I issue a POST request from a Web API client application I get a 404 as well and the message:

No HTTP resource was found that matches the request URI

I've created a test website with MVC 4 and Web API as well and deployed it on the same server and the Web API works. Web API and MVC assemblies have the same version number in both projects.

Furthermore I have added the Web API Route Debugger to the application. If I use a valid route like http://myserver/api/order/12 I get the following result:

For me this means that the correct route template Api/{Controller}/{Id} has been found and correctly parsed into a controller Order and Id=12. The controller (derived from ApiController) exists in the web assembly where also all MVC controllers are.

However, I don't know what the status 000 could mean and why there is no "Route selecting" section displayed (which is normally the case even if the assembly doesn't contain a single ApiController, see screenshots on the linked page above). Somehow it looks like no ApiController is found or even not searched for or the search fails silently.

The IIS log files don't show anything useful. Changing various application pool settings and using the same app pool for the test and the real application didn't help.

I am currently in the process to remove "features", configuration settings, third party assemblies, etc. from the application to bring it down to the small size of the test application in the end and hoping that at some point it starts to work.

Does somebody have a clue what the issue could be? Also any debugging or logging idea to possibly find the reason is very welcome.

Edit

Thanks to Darrel Miller's tip in the comments below I have integrated Tracing for ASP.NET Web Api.

For the (GET) request URL http://myserver/api/order/12 I get the following:

  • In development environment, successful (in short form):

Message: http://localhost:50020/api/order/12; Category: System.Web.Http.Request

Controller selection and instantiation...

Operator: DefaultHttpControllerSelector; Operation: SelectController; Message: Route="controller:order,id:12"; Category: System.Web.Http.Controllers

Operator: DefaultHttpControllerSelector; Operation: SelectController; Message: Order; Category: System.Web.Http.Controllers

Operator: HttpControllerDescriptor; Operation: CreateController; Message: ; Category: System.Web.Http.Controllers

Operator: DefaultHttpControllerActivator; Operation: Create; Message: ; Category: System.Web.Http.Controllers

Operator: DefaultHttpControllerActivator; Operation: Create; Message: MyApplication.ApiControllers.OrderController; Category: System.Web.Http.Controllers

Action selection, parameter binding and action invocation follows...

Content negotiation and formatting for result...

Operator: DefaultContentNegotiator; Operation: Negotiate; Message: Typ = "String" ... more

Disposing the controller...

Operator: OrderController; Operation: Dispose; Message: ; Category: System.Web.Http.Controllers

  • In production environment, not successful (in short form):

Message: http://myserver/api/order/12; Category: System.Web.Http.Request

Operator: DefaultHttpControllerSelector; Operation: SelectController; Message: Route="controller:order,id:12"; Category: System.Web.Http.Controllers

The whole part of controller activation, action selection, parameter binding, action invocation is missing and it follows content negotiation and formatting for the error message immediately:

Operator: DefaultContentNegotiator; Operation: Negotiate; Message: Type = "HttpError" ... more

解决方案

Thanks to Kiran Challa's comment and source code from this answer I was able to figure out that an assembly (the ReportViewer 11 assembly for SQL Server Reporting Services) was missing on the production server.

Although no ApiController is in this assembly it seems to cause that controllers in assemblies - in this case my Web project's assembly - that are referencing the missing assembly are not found.

Apparently this behaviour is related to this piece of code from the Web API's DefaultHttpControllerTypeResolver source:

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

I don't know if it has to be this way and I am not quite convinced by the comment in the code but this catch ... continue block is rather silent about a possible problem and it took me a huge amount of time and frustration to find it. I even knew that the ReportViewer wasn't installed yet. I tried to install it and dependent assemblies but it was blocked by another running process on the server, so I decided to postpone the installation until I could contact the administrator and focus on MVC and WebAPI testing first - big mistake! Without Kiran's debugging code snippet I had never had the idea that the existence of a ReportViewer.dll could have anything to do with controller type resolution.

In my opinion there is room for improvement for the average developer like me who doesn't have a deeper knowledge about the inner workings of Web API.

After installing the missing ReportViewer.dll the problem disappeared.

Here are questions about the same symptom which might have the same reason:

Edit

I have issued a request for improvement on CodePlex:

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

Edit 2 (Aug 11 '13)

The issue has been fixed for WebAPI v5.0 RC. See the link above to the workitem and its comments section for details.

这篇关于对 ASP.NET Web API 的所有请求都返回 404 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆