我有一个包含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 Route Debugger添加到应用程序中。如果我使用像http://myserver/api/order/12
这样的有效路线,我会得到以下结果:
对我来说,这意味着找到了正确的路由模板Api/{Controller}/{Id}
,并将其正确解析为控制器Order
和Id=12
。控制器(派生自ApiController
)存在于Web程序集中,其中所有MVC控制器都是。
但是,我不知道状态000
可能意味着什么以及为什么没有显示“路由选择”部分(即使程序集不包含单个{{1)也是如此,请参阅上面链接页面上的截图)。不知怎的,它看起来没有找到ApiController
甚至没有被搜索过,或者搜索无声地失败。
IIS日志文件没有显示任何有用的内容。更改各种应用程序池设置并使用相同的应用程序池进行测试和实际应用程序没有帮助。
我目前正在从应用程序中删除“功能”,配置设置,第三方程序集等,最终将其降低到测试应用程序的小尺寸,并希望它在某些时候启动工作。
有人知道问题是什么吗?此外,任何可能找到原因的调试或记录想法都是非常受欢迎的。
修改
感谢Darrel Miller在下面评论中的提示,我已经整合了Tracing for ASP.NET Web Api。
对于(GET)请求网址ApiController
,我得到以下内容:
消息:
http://myserver/api/order/12
;类别: System.Web.Http.Request控制器选择和实例化......
运算符:DefaultHttpControllerSelector;操作:SelectController; 消息:Route =“controller:order,id:12”;类别: System.Web.Http.Controllers
运算符:DefaultHttpControllerSelector;操作:SelectController; 消息:订单;类别:System.Web.Http.Controllers
运算符:HttpControllerDescriptor;操作:CreateController; 信息: ;类别: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://localhost:50020/api/order/12
;类别: System.Web.Http.Request运算符:DefaultHttpControllerSelector;操作:SelectController; 消息:Route =“controller:order,id:12”;类别: System.Web.Http.Controllers
缺少控制器激活,操作选择,参数绑定,操作调用的整个部分,它遵循内容 立即协商和格式化错误消息:
运算符:DefaultContentNegotiator;操作:谈判;信息: Type =“HttpError”... more
答案 0 :(得分:23)
感谢来自Kiran Challa's的this answer评论和源代码,我能够发现生产服务器上缺少程序集(SQL Server Reporting Services的ReportViewer 11 assembly
)。< / p>
虽然此程序集中没有ApiController
,但似乎导致找不到程序集中的控制器 - 在本例中是我的Web项目的程序集 - 引用了缺少的程序集。
显然,这种行为与Web API's DefaultHttpControllerTypeResolver
来源的这段代码有关:
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的调试代码片段,我从未想过ReportViewer.dll
的存在可能与控制器类型解析有关。
在我看来,对于像我这样对Web API内部工作没有更深入了解的普通开发人员来说还有改进的空间。
安装缺失的ReportViewer.dll
后,问题就消失了。
以下是与可能有相同症状的相同症状的问题:
修改强>
我已经发出了对CodePlex的改进请求:
http://aspnetwebstack.codeplex.com/workitem/1075
编辑2(2013年8月11日)
此问题已针对WebAPI v5.0 RC修复。有关详细信息,请参阅上面的工作项及其注释部分链接。
答案 1 :(得分:5)
在这个答案中有很多资源,然而,我得到了404因为结果是一个非常愚蠢的原因:
事实证明,我错过了打包并将 Global.asax 部署到部署中虚拟目录的根目录。在这里添加这个为了像我这样的傻瓜的好处:)
答案 2 :(得分:0)
我在远程服务器上遇到了同样的问题,但是当我在localhost上执行时工作正常。
我的解决方案是:
<system.webServer>
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0"
type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
</system.webServer>
我希望,这对你有用。