在IIS7上出现WebApi的{"message":"发生了错误"},但在IIS Express中没有。

189
我正在使用ASP.NET MVC 4 WebApi并在本地计算机上通过IIS Express运行它,感觉很有趣。我已经配置了IIS Express以服务于远程计算机,所以我的公司其他人正在使用我的电脑作为我们的Web服务器。

但后来我们认为这不是最佳解决方案,因此安装了.NET 4.5,并将WebApi放到远程服务器上。当我使用Fiddler发送POST请求到本地机器上的控制器时,它会返回正确的响应,但是当我将域更改为运行IIS7的Web服务器时,相同的POST请求会返回一个加密的

{"message":"an error has occurred"}

消息。有没有人知道出了什么问题?


2
错误响应的HTTP状态码是什么?如果它是500,那么很可能是使用IIS 7的远程机器上的网站/应用程序配置无效。在远程机器上创建一个简单的HTML文件,如果可能,在远程机器上浏览它以确保它可以被查看,然后尝试从您的机器访问它,看看是否成功。 - Sixto Saez
这是一个500错误。感谢您的建议,但WebApi提供的默认index.html页面可以正常工作。另外需要补充说明的是,一些API Web服务可以正常工作,而另一些则不能,在我的本地机器上所有服务都可以正常工作。 - nsg
2
你需要启用IIS请求跟踪,以获取更多细节信息,当你看到500错误时。500错误通常发生在Web API路由之前,但我猜可能是由于你的代码触发了它。查看IIS跟踪日志,看看是否提供任何线索。 - Sixto Saez
1
你可以通过在服务器机器本身上启动浏览器(例如使用远程桌面会话)来发起请求,从而让服务器在其响应中提供更详细的错误信息。 - Jon Schneider
9个回答

298
问题是缺失依赖项,该依赖项不在服务器上,而是在我的本地机器上。在我们的情况下,它是Devart.Data.Linq dll。
为了得到这个答案,我打开了IIS跟踪来追踪500错误。这提供了一些信息,但真正有用的是在web.config中设置,这指出了缺失动态加载依赖项。添加该依赖项并将其设置为本地复制后,服务器开始工作。

41
当HTTP响应代码为500且启用自定义错误时,WebAPI似乎会用{"message":"an error has occurred"}代替真正的响应。感谢指点。 - Paul Suart
5
关于设置customErrors模式的建议很好。我很惊讶地发现更改它会对这些错误的输出产生影响。请问还有其他需要翻译的内容吗? - Dewi Rees
1
你还可以将其设置为 mode="RemoteOnly",如果在服务器上的Web浏览器上运行页面,则还可以查看错误,而不会影响站点的其他部分的安全性。 - Simon_Weaver
1
当更改设置不可能时(例如,由于API部分托管在符合PCI标准的服务器上而在机器级别禁用了错误),如何获得此类错误详细信息的建议?我尝试设置Elmah,但不幸的是它没有记录任何内容。 - Scott Salyer
救命稻草。这个好选择帮助我找到了连接字符串中错误的数据库名称。谢谢 :) - Marty_in_a_Box
显示剩余2条评论

104

基本上:

如果CustomErrors无法解决问题(例如,如果您的ASP.NET堆栈是>2012),请使用IncludeErrorDetailPolicy

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy 
= IncludeErrorDetailPolicy.Always;

注意:返回详细的错误信息可能会向'黑客'泄露敏感信息,请参见下面这个答案中Simon的评论。

TL;DR版本

对我而言,CustomErrors并没有真正帮助我。它已经被设置为Off,但我仍然只收到了一个微不足道的发生了错误消息。我猜验收答案是3年前的,而在当今网络世界里,这是很长的时间。我正在使用Web API 2和ASP.NET 5(MVC 5),而微软已经摆脱了仅适用于IIS的策略,而CustomErrors是老派的IIS ;)。

无论如何,我遇到了一个本地没有的产品问题。然后发现我不能像在我的开发机器上那样在Chrome的网络选项卡中查看错误。最后,我通过在生产服务器上安装Chrome,然后在服务器本身上浏览应用程序(例如在“localhost”上)来解决了这个问题。然后更详细的错误信息出现了,并显示了堆栈跟踪等信息。

之后我才发现Jimmy Bogard的这篇文章(注:Jimmy是自动映射器先生!)。有趣的是,他的文章也是来自2012年,但在其中,他已经解释了CustomErrors不再起作用,但您可以通过在全局WebApi配置中设置不同的IncludeErrorDetailPolicy(例如:WebApiConfig.cs)来更改“错误详细信息”:

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy 
= IncludeErrorDetailPolicy.Always;

幸运的是,他还解释了如何设置Web API(2)以便听取您的CustomErrors设置。这是一个相当合理的方法,这使您可以回到2012年:P。

注意:默认值为“LocalOnly”,这就解释了为什么在找到这篇文章之前我能够用我描述的方式解决问题。但我知道并非每个人都可以远程连接到生产环境并启动浏览器(直到我决定自由职业和DevOps)。


2
现在,这个可以工作了。谢谢!我有一些内存集成OWIN测试,在构建服务器上失败,但在本地没有问题。有了我的启动类中的这个设置,我可能有机会找出原因。 - Thomas Eyde
当使用Microsoft.AspNet.WebApi.WebHost在IIS中托管时,似乎customError设置与WebApi 2一起工作。这些包的版本为5.2.3,因此ASP.NET堆栈远远超过2012年。将其设置为Off后,Web API从通用错误切换到更详细的错误,包含调用堆栈等信息... - tstojecki
4
设置时要小心,因为它可能会向“黑客”揭示敏感信息。我经常会使用类似于if (DateTime.Now < new DateTime(2017, 6, 22)) { .... }的快速hack来设置这样的选项。然后我可以在生产环境中测试它,如果我忘记禁用它,明天它将神奇地恢复到正常行为。 - Simon_Weaver
这里也有一篇关于此的好文章: https://lostechies.com/jimmybogard/2012/04/18/custom-errors-and-error-detail-policy-in-asp-net-web-api/ - santos

41

其他答案对我都没有用。

这个有用:(在Startup.cs中)

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();

        WebApiConfig.Register(config);

        // Here: 
        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    }
}
< p >(或者您可以将其放在WebApiConfig.cs中):

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // Here: 
        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    }
}

是的!这是我在Mono/Linux上唯一可行的解决方案。 - John Doe
这对我在IIS和Windows Server上内部提供的应用程序的生产环境中有效。 - Paul Carlton
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; 帮助我找到了问题所在,原来是我返回了一个无法解析的实体实例,因为上下文已经被释放掉了。非常感谢! - Jood jindy

18

每当我在测试环境中遇到错误,并且记得“我以前做过这个,但可以通过直接在web.config中进行更改而不必修改代码并重新部署到测试环境,但需要进行两次更改……又是什么来着?”时,我总是会回到这个问题。

供日后参考

<system.web>
   <customErrors mode="Off"></customErrors>
</system.web>

<system.webServer>
  <httpErrors errorMode="Detailed" existingResponse="PassThrough"></httpErrors>
</system.webServer>

14

如果有人需要帮助,可能以下信息会对您有所帮助:

我曾经遇到相似的问题,在按照Nate的指示进行操作后,我加入了以下内容:

<system.web>
     <customErrors mode="Off"/>
 </system.web>

这给我展示了更多有关错误的信息:

"ExceptionMessage": "无法加载指定的元数据资源。", "ExceptionType": "System.Data.Entity.Core.MetadataException", "StackTrace": " at System.Data.Entity.Core.Metadata.Edm.MetadataArtifactLoaderCompositeResource.LoadResources(...

这时我想起自己已经将edmx文件移动到另一个位置,但忘记修改配置文件中的connectionstrings节点(使用"configSource"将connectionsstrings节点放在单独的文件中,但那是另一个故事)。


当我在asp.net的web api中添加OData和AutoMapper时遇到了这个问题 - 希望这些关键词可以帮助某人找到这篇文章,而我的情况下try/catch不起作用,所以我必须查看原始结果。 - Ekus

12

当我向WebAPI端点发布内容时,遇到了类似的问题。将CustomErrors设置为Off后,我能够看到实际的错误信息,发现其中一个dll文件丢失。


0

我的Swagger XML文件没有部署到\bin目录下:

GlobalConfiguration.Configuration
  .EnableSwagger(c =>
  {
    c.SingleApiVersion("v1", "SwaggerDemoApi");
    c.IncludeXmlComments(string.Format(@"{0}\bin\SwaggerDemoApi.XML", 
                         System.AppDomain.CurrentDomain.BaseDirectory));
    c.DescribeAllEnumsAsStrings();
  })

http://wmpratt.com/swagger-and-asp-net-web-api-part-1/

enter image description here

必须在发布配置和调试配置中进行设置。


0

如果在你的 .NET Framework 的 machine.config 文件中有 <deployment retail="true"/>,你将看不到详细的错误信息。请确保该设置为 false 或不存在。


0

所以我尝试了所有建议的解决方案,但都没有成功。 我所做的只是从服务器运行应用程序,并显示完整的错误信息,当我将customErrors模式设置为false时,这应该可以工作,但它没有。当我从服务器浏览API时,我能够看到问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接