【问题标题】:WCF Data Service returns 400 Bad Request for POST queriesWCF 数据服务为 POST 查询返回 400 Bad Request
【发布时间】:2010-06-19 14:24:16
【问题描述】:

我需要托管 WCF 数据服务,作为在 IIS 7 集成模式下运行的旧版 ASP.NET MVC 网站的一部分。

对 Web 服务的读取访问工作正常,但每当我尝试 POST 到 Web 服务时,都会收到 400 Bad Request 错误。

出于测试目的,我从http://www.odata.org/developers/odata-sdk#/media/7582/odatasampleservices.zip 下载了示例odata 服务。在单独的 IIS 网站中运行时,发布到该 Web 服务可以正常工作。但是,当我将它放在我的旧网站中时,我再次向服务发送发布请求时收到 400 Bad Request 错误。

因此问题似乎与我的 ASP.NET MVC 项目的配置有关。但是,我不知道如何进行。

这是我在旧项目中使用的网络配置文件:

<?xml version="1.0" encoding="utf-8"?>
<!-- 
 Note: As an alternative to hand editing this file you can use the 
 web admin tool to configure settings for your application. Use
 the Website->Asp.Net Configuration option in Visual Studio.
 A full list of settings and comments can be found in 
 machine.config.comments usually located in 
 \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
 <configSections>
 <section name="combres" type="Combres.ConfigSectionSetting, Combres" />
 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net" />
 <sectionGroup name="elmah">
  <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
  <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
  <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
  <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
  <section name="errorMailSAZ" requirePermission="false" type="ElmahFiddler.ElmahMailSAZSectionHandler, ElmahFiddler" />
 </sectionGroup>
 </configSections>

 <combres definitionUrl="~/App_Data/combres.xml" />
 <log4net>
 <root>
  <level value="ALL" />
  <appender-ref ref="RollingFile" />
 </root>
 <logger name="Combres">
  <level value="DEBUG" />
 </logger>
 <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
  <file value="log.txt" />
  <appendToFile value="true" />
  <maximumFileSize value="100KB" />
  <maxSizeRollBackups value="2" />
  <layout type="log4net.Layout.PatternLayout">
  <conversionPattern value="%d [%t] %-5p %c - %m%n" />
  </layout>
 </appender>
 </log4net>
 <appSettings configSource="appSettings.config" />
 <connectionStrings configSource="connectionstrings.config">

 </connectionStrings>
 <!-- Mail server settings-->
 <system.net>
    <mailSettings/>
 </system.net>
 <system.web>
 <globalization uiCulture="de" culture="de-DE" />

 <compilation debug="true">
  <assemblies>
  <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <add assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
  <add assembly="Microsoft.ReportViewer.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
  <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  </assemblies>
  <buildProviders>
  <add extension=".rdlc" type="Microsoft.Reporting.RdlBuildProvider, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </buildProviders>
 </compilation>

 <authentication mode="Forms">
  <!-- User muessen sich nach 30 Tagen abwesenheit neu einloggen (wenn remember me angeklickt wird)-->
  <forms loginUrl="~/Profile/LogOn" timeout="43200" slidingExpiration="true" />
 </authentication>
 <membership>
  <providers>
  <clear />
  <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="500" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/" />
  </providers>
 </membership>
 <profile>
  <providers>
  <clear />
  <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" applicationName="/" />
  </providers>
 </profile>
 <roleManager enabled="true">
  <providers>
  <clear />
  <add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  <add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </providers>
 </roleManager>
 <customErrors configSource="customErrors.config" />
 <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
  <namespaces>
  <add namespace="System.Web.Mvc" />
  <add namespace="System.Web.Mvc.Ajax" />
  <add namespace="System.Web.Mvc.Html" />
  <add namespace="System.Web.Routing" />
  <add namespace="System.Linq" />
  <add namespace="System.Collections.Generic" />
  <add namespace="xVal.Html" />
  <add namespace="Zeiterfassung.Views" />
  <add namespace="Zeiterfassung.Models" />
  <add namespace="Zeiterfassung" />
  <add namespace="GrigoreComponents.Generic" />
  <add namespace="DeverMind.Generic" />
  <!--<add namespace="MvcContrib.UI.Grid.ActionSyntax" />-->
  </namespaces>
 </pages>
 <httpHandlers>
  <add path="captcha.ashx" verb="GET" type="ManagedFusion.Web.Mvc.Handlers.CaptchaImageHandler, ManagedFusion, Version=1.0.3490.29346, Culture=neutral" validate="false" />
  <add path="*.mvc" verb="*" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" validate="false" />
  <!--<add path="VSEnterpriseHelper.axd" verb="GET" type="Microsoft.VisualStudio.Enterprise.Common.AspNetHelperHandler, Microsoft.VisualStudio.Enterprise.ASPNetHelper, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />-->
  <add path="Reserved.ReportViewerWebControl.axd" verb="*" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="false" />
  <add path="/elmah.axd" verb="POST,GET,HEAD" type="Elmah.ErrorLogPageFactory, Elmah" />
 </httpHandlers>
 <httpModules>
  <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
 </httpModules>
 </system.web>
 <system.web.extensions>
 <scripting>
  <webServices>
  <authenticationService enabled="true" requireSSL="false" />
  </webServices>
 </scripting>
 </system.web.extensions>
 <!-- 
  The system.webServer section is required for running ASP.NET AJAX under Internet
  Information Services 7.0. It is not necessary for previous version of IIS.
 -->
 <system.webServer>

 <validation validateIntegratedModeConfiguration="false" />
 <modules runAllManagedModulesForAllRequests="true">
  <add name="Elmah.ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
  <add name="Elmah.ErrorFilter" type="Elmah.ErrorFilterModule" preCondition="managedHandler" />
  <add name="Elmah.ErrorMail" type="Elmah.ErrorMailModule" preCondition="managedHandler" />
  <add name="elmahSAZ" type="ElmahFiddler.ElmahMailSAZTraceModule, ElmahFiddler" />
 </modules>
 <handlers>
  <add name="Elmah" path="elmah.axd" verb="POST,GET,HEAD" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
  <remove name="MvcHttpHandler" />
  <remove name="UrlRoutingHandler" />
  <add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <!--<add name="VSEnterpriseHelper.axd" verb="GET" path="VSEnterpriseHelper.axd" preCondition="integratedMode" type="Microsoft.VisualStudio.Enterprise.Common.AspNetHelperHandler, Microsoft.VisualStudio.Enterprise.ASPNetHelper, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>-->
  <add name="ReportViewerWebControlHandler" preCondition="integratedMode" verb="*" path="Reserved.ReportViewerWebControl.axd" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
 </handlers>
 <!--404 fehler sind was besonderes, ich will sie nicht in elmah sehen und ausserdem funktioniert es aus unbekannten gruenden eh nicht wenn ich sie auf dem hetzner-server per 
 customerrors handle-->
 <httpErrors>
  <remove statusCode="404" subStatusCode="-1" />
  <error statusCode="404" prefixLanguageFilePath="" path="/Error/FileNotFound" responseMode="ExecuteURL" />
 </httpErrors>
 <staticContent>
  <!--cache static content on the client side for 7 days-->
  <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
 </staticContent>
 <rewrite>
  <rules>
  <rule name="CanonicalHostName-Adrian" enabled="true" stopProcessing="true">
   <match url="(.*)" />
   <conditions>
   <add input="{HTTP_HOST}" pattern="^worklogger\.de:4567$" />
   </conditions>
   <action type="Redirect" url="http://www.worklogger.de:4567/{R:1}" />
  </rule>
  <rule name="CanonicalHostName-Sandra" enabled="true" stopProcessing="true">
   <match url="(.*)" />
   <conditions>
   <add input="{HTTP_HOST}" pattern="^worklogger\.de:7654$" />
   </conditions>
   <action type="Redirect" url="http://www.worklogger.de:7654/{R:1}" />
  </rule>
  <rule name="CanonicalHostName-Production" enabled="true" stopProcessing="true">
   <match url="(.*)" />
   <conditions>
   <add input="{HTTP_HOST}" pattern="^logmytime\.de$" />
   </conditions>
   <action type="Redirect" url="http://www.logmytime.de/{R:1}" />
  </rule>
  <rule name="RemoveTrailingSlashRule1" enabled="true" stopProcessing="true">
   <match url="(.*)/$" />
   <conditions>
   <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
   <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
   </conditions>
   <action type="Redirect" url="{R:1}" />
  </rule>
  <rule name="Rewrite rule for RewriteMap" enabled="true" stopProcessing="true">
   <match url=".*" />
   <conditions>
   <add input="{RewriteMap:{REQUEST_URI}}" pattern="(.+)" />
   </conditions>
   <action type="Redirect" url="{C:1}" appendQueryString="false" />
  </rule>
  <rule name="jquery-UI images" enabled="true" stopProcessing="true">
   <match url="(.*)combres.axd/UserAreaCSS/images/(.*)" />
   <conditions logicalGrouping="MatchAny"></conditions>
   <action type="Rewrite" url="Scripts/jquery-ui/css/custom-theme/images/{R:2}" />
  </rule>
    <rule name="Add API trailing slash without redirecting the user to a different domain" enabled="false" patternSyntax="ExactMatch" stopProcessing="true">
     <match url="API/V1/APi.svc" />
     <action type="Redirect" url="API/V1/APi.svc/" redirectType="Permanent" />
    </rule>
  </rules>
  <rewriteMaps>
  <rewriteMap name="RewriteMap">

   <add key="/Zeiterfassung/zeiterfassungssoftware.html" value="/Zeiterfassung/Arbeitszeit/Zeiterfassungssoftware" />
  </rewriteMap>
  </rewriteMaps>
 </rewrite>
 </system.webServer>
 <runtime>
 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  <dependentAssembly>
  <assemblyIdentity name="Microsoft.VisualStudio.Enterprise.ASPNetHelper" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <codeBase version="9.0.0.0" href="file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio%209.0/Common7/IDE/PrivateAssemblies/Microsoft.VisualStudio.Enterprise.ASPNetHelper.DLL" />
  </dependentAssembly>
  <dependentAssembly>
  <assemblyIdentity name="Microsoft.VisualStudio.Enterprise.ASPNetHelper" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <codeBase version="9.0.0.0" href="file:///C:/Program%20Files%20(x86)/Microsoft%20Visual%20Studio%209.0/Common7/IDE/PrivateAssemblies/Microsoft.VisualStudio.Enterprise.ASPNetHelper.DLL" />
  </dependentAssembly>
  <dependentAssembly xmlns="">
  <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
  <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
  </dependentAssembly>
 </assemblyBinding>
 </runtime>
 <location path="VSEnterpriseHelper.axd">
 <system.web>
  <authorization>
  <allow users="?" />
  </authorization>
 </system.web>
 </location>
 <!-- Deny everyone except siteadmins to see the elmah.axd -->
 <location path="elmah.axd">
 <system.web>
  <authorization>
  <allow roles="SiteAdmin" />
  <deny users="*" />
  </authorization>
 </system.web>
 </location>
 <system.serviceModel>
 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
 </system.serviceModel>
</configuration>

感谢您的帮助,

阿德里安

编辑:不确定是否有任何帮助,但这是提琴手输出和失败的请求跟踪:

> curl -u 登录:通过 > “http://www.worklogger.de:4567/Testapi/Testapi.svc/Projects” > -v -d 测试 > * 即将 connect() 到 www.worklogger.de 端口 4567 (#0) > * 正在尝试 192.168.0.109... 已连接 > * 连接到 www.worklogger.de (192.168.0.109) 端口 4567 (#0) > * 使用 Basic 和用户“登录”的服务器身份验证 > POST /Testapi/Testapi.svc/Projects HTTP/1.1 > 授权:基本 bG9naW46cGFzcw== > 用户代理:curl/7.19.0 (i686-suse-linux-gnu) libcurl/7.19.0 OpenSSL/0.9.8h zlib/1.2.3 libidn/1.10 > 主办方:www.worklogger.de:4567 > 接受:*/* > 内容长度:4 > 内容类型:application/x-www-form-urlencoded >

我将失败的请求跟踪保存到 pastebin 到 http://pastebin.com/K3uEZfVS,因为 StackOverflow 不允许帖子增长超过 50k。

Edit2:我想再次指出,当将它放入一个没有其他更改的全新 ASP.NET MVC 网站时,同样的 Web 服务运行良好(POST 和 GET!)。因此,问题与我提出请求的方式无关。

【问题讨论】:

  • 愚蠢的问题,但是您是否排除了 MVC 处理 WCF 服务的路径?我是否正确理解了获取请求工作正常的问题?
  • @R0MANARMY:是的,获取请求可以正常工作。是的,我在 globals.asax 文件中排除了 Web 服务的路径。
  • 另一个愚蠢的问题 - 你检查了所有机器之间的防火墙规则吗?
  • @Oded:我在本地主机上测试时遇到了这个问题。此外,错误 400 Bad Request 意味着 IIS 认为请求格式不正确,因此没有将其交给应用程序处理。这将要求 IIS 首先接收请求...
  • 您是否尝试在 fiddler 上运行它并捕获网络流量?可能会给你更多的线索。

标签: asp.net wcf iis wcf-data-services odata


【解决方案1】:
  • 您是否尝试在上面发布的 web.config 中将 aspNetCompatibilityEnabled 设置为 false?

如果 WCF 服务的代码中未设置相应的属性(默认为 AspNetCompatibilityRequirementsMode.NotAllowed),则服务拒绝来自任何将 aspNetCompatibilityEnabled 设置为 true 的客户端的调用。

  • 如果该设置有问题,请在此处 是长期修复,我已添加 attribute [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 到我的 WCF 服务类

【讨论】:

  • 我尝试将此属性添加到我的 WCF 数据服务,但它似乎没有任何效果。 400 Bad Request Error 仍然存在。
  • 在我的情况下,要使属性生效,我必须 SelfHost 服务(手动执行 serviceHost.Open() 而不是 IIS 按需执行)。排除兼容性问题的一个简单方法是在 aspNetCompatibilityEnabled 设置为 false 时调用服务,您可以这样做吗?
  • 第二次认为我的情况略有不同,aspNetCompatibilityEnabled=true 与 WCF 服务在同一个应用程序中,这阻止了客户端得到答复
  • 你能在调试模式下单步执行吗?应该有错误或异常抛出
  • worklogger.de:4567/Testapi/Testapi.svc/Projects”或“worklogger.de:4567/Testapi/Testapi.svc”是否在浏览器中打开?还是有调用栈、异常、内部异常的死黄页?
【解决方案2】:

我通过实现网络服务代理解决了这个问题:http://code.google.com/p/fastajaxproxy/

【讨论】:

    【解决方案3】:

    在 IIS 中禁用 WebDav。它对我有用...大多数时候,post 方法用于执行删除或放置操作。禁用此功能可使 post 执行删除和放置操作

    【讨论】:

    • 我没有故意在我的项目中启用 WebDav。这是默认启用的吗?
    【解决方案4】:

    如果您要发布文件,请查看此问题中建议的设置:WCF problem with uploading large file, hosted in IIS

    (以及以下答案)。

    希望对你有帮助

    【讨论】:

    • 谢谢,但我什至没有发布文件。只是一个带有一个参数的小测试 POST 请求。
    【解决方案5】:

    此服务托管在哪个操作系统上?
    如果是 Vista 或更高版本,您可以使用 FREB 来解码管道中失败的内容。 http://learn.iis.net/page.aspx/266/troubleshooting-failed-requests-using-tracing-in-iis-7/ 你能运行 Fiddler 来识别来自服务器的 HTTP 错误响应是什么吗?

    【讨论】:

    • 感谢您的帮助,但我已经在我的 OP 中发布了失败的请求跟踪以及 curl 的成绩单。
    • Adrian,FREB 跟踪不同于使用 CURL 的 HTTP 跟踪。 CURL 正在跟踪服务器发送给客户端的 HTTP 数据包。 FREB 跟踪将调试 iis 工作进程,为您提供有关请求失败并出现 HTTP 400 错误请求的原因。
    • 我明白什么是失败的请求跟踪。如果您仔细阅读 OP,您会注意到一个指向 pastebin.com/K3uEZfVS 的链接,它准确地显示了您所要求的 - 一个失败的请求跟踪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多