WCF服务返回400错误:无法读取消息正文,因为它是空的

时间:2010-10-14 14:26:50

标签: c# wcf datacontract

我有一个令人头疼的WCF服务。我已启用跟踪,我有一个正在构建并传入数据协定的对象,但我在日志中看到此错误:

<TraceData>
            <DataItem>
                <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
                    <TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier>
                    <Description>Throwing an exception.</Description>
                    <AppDomain>efb0d0d7-1-129315381593520544</AppDomain>
                    <Exception>
                        <ExceptionType>System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
                        <Message>There is a problem with the XML that was received from the network. See inner exception for more details.</Message>
                        <StackTrace>
                            at System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
                            at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
                            at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
                            at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
                            at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
                            at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
                            at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
                            at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
                            at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
                        </StackTrace>
                        <ExceptionString>
                            System.ServiceModel.ProtocolException: There is a problem with the XML that was received from the network. See inner exception for more details. ---&amp;gt; System.Xml.XmlException: The body of the message cannot be read because it is empty.
                            --- End of inner exception stack trace ---
                        </ExceptionString>
                        <InnerException>
                            <ExceptionType>System.Xml.XmlException, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
                            <Message>The body of the message cannot be read because it is empty.</Message>
                            <StackTrace>
                                at System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
                                at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
                                at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
                                at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
                                at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
                                at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
                                at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
                                at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
                                at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
                            </StackTrace>
                            <ExceptionString>System.Xml.XmlException: The body of the message cannot be read because it is empty.</ExceptionString>
                        </InnerException>
                    </Exception>
                </TraceRecord>
            </DataItem>
        </TraceData>

所以,这是我的服务界面:

[ServiceContract]
    public interface IRDCService
    {
        [OperationContract]
        Response<Customer> GetCustomer(CustomerRequest request);

        [OperationContract]
        Response<Customer> GetSiteCustomers(CustomerRequest request);
    }

这是我的服务实例

public class RDCService : IRDCService
    {
        ICustomerService customerService;

        public RDCService()
        {
            //We have to locate the instance from structuremap manually because web services *REQUIRE* a default constructor
            customerService = ServiceLocator.Locate<ICustomerService>();
        }

        public Response<Customer> GetCustomer(CustomerRequest request)
        {
            return customerService.GetCustomer(request);
        }

        public Response<Customer> GetSiteCustomers(CustomerRequest request)
        {
            return customerService.GetSiteCustomers(request);
        }
    }

Web服务(服务器端)的配置如下所示:

<system.serviceModel>
        <diagnostics>
            <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
                logMessagesAtTransportLevel="true" />
        </diagnostics>
        <services>
            <service behaviorConfiguration="MySite.Web.Services.RDCServiceBehavior"
                name="MySite.Web.Services.RDCService">
                <endpoint address="http://localhost:27433" binding="wsHttpBinding"
                    contract="MySite.Common.Services.Web.IRDCService">
                    <identity>
                        <dns value="localhost:27433" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="MySite.Web.Services.RDCServiceBehavior">
                    <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                    <serviceMetadata httpGetEnabled="true"/>
                    <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="true"/>


                    <dataContractSerializer maxItemsInObjectGraph="6553600" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>

这是我的请求对象的样子

[DataContract]
    public class CustomerRequest : RequestBase
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public int SiteId { get; set; }
    }

RequestBase:

[DataContract]
    public abstract class RequestBase : IRequest
    {
        #region IRequest Members

        [DataMember]
        public int PageSize { get; set; }

        [DataMember]
        public int PageIndex { get; set; }

        #endregion
    }

我的IRequest界面

public interface IRequest
    {
        int PageSize { get; set; }
        int PageIndex { get; set; }
    }

我的服务调用周围有一个包装类。这是班级。

public class MyService : IMyService
    {
        IRDCService service;

        public MyService()
        {
            //service = new MySite.RDCService.RDCServiceClient();
            EndpointAddress address = new EndpointAddress(APISettings.Default.ServiceUrl);
            BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
            binding.TransferMode = TransferMode.Streamed;
            binding.MaxBufferSize = 65536;
            binding.MaxReceivedMessageSize = 4194304;

            ChannelFactory<IRDCService> factory = new ChannelFactory<IRDCService>(binding, address);
            service = factory.CreateChannel();
        }

        public Response<Customer> GetCustomer(CustomerRequest request)
        {
            return service.GetCustomer(request);
        }

        public Response<Customer> GetSiteCustomers(CustomerRequest request)
        {
            return service.GetSiteCustomers(request);
        }
    }

最后是响应对象。

[DataContract]
    public class Response<T>
    {
        [DataMember]
        public IEnumerable<T> Results { get; set; }

        [DataMember]
        public int TotalResults { get; set; }

        [DataMember]
        public int PageIndex { get; set; }

        [DataMember]
        public int PageSize { get; set; }

        [DataMember]
        public RulesException Exception { get; set; }
    }

因此,当我构建我的CustomerRequest对象并将其传入时,由于某种原因,它将作为空请求命中服务器。有什么想法吗?我试过提高对象图和消息大小。当我调试时,它会在400错误的包装类中停止。我不确定是否存在序列化错误,但考虑到对象契约是4个整数属性,我无法想象它会导致问题。

6 个答案:

答案 0 :(得分:2)

如果遇到此问题,则需要在本地IIS上运行WCF应用程序。

转到wcf应用程序项目的Properties,然后选择“Use local iis web server”。

您需要启用Microsoft .Net Framework 3.1 - &gt; Windows通信基础http激活添加/删除Windows功能。

打开visual studio命令窗口

然后你必须运行aspnet_regiis -i

您需要运行servicemodelreg -ia

这是很多运行,得到一个错误,搜索谷歌,冲洗,重复。大约需要一个小时才能搞清楚。 PITA。

答案 1 :(得分:2)

我遇到了同样的问题,显然这是由URL中的.svc后面的斜尾斜线引起的。不要把斜线放在那里......它有效。

答案 2 :(得分:2)

我遇到了同样的问题,但是由不同的问题引起了。

我为WCF REST服务实现了自己的服务主机,并意外地从System.ServiceModel.ServiceHost而不是System.ServiceModel.Web.WebServiceHost

派生了我的课程

我可以通过浏览到根URL来激活服务,但是当我尝试访问其中一个公开的资源时,我会收到HTTP 400错误。连接调试器显示了上面提到的异常。

希望有一天能帮到某人。

答案 3 :(得分:1)

我们多次遇到同样的问题,请在IIS上托管,在性能和可扩展性方面要好得多。

当WCF服务出现问题,并且堕落或太忙时。这个问题有时会发生。

此致

Mazhar Karimi

答案 4 :(得分:0)

发生同样的错误消息是由于在App.config中将端点绑定设置为basicHttpBinding引起的(即使System.ServiceModel.Web.WebServiceHost被用作@MvdD的答案):

<endpoint address="" binding="basicHttpBinding" contract="MySite.Common.Services.Web.IRDCService">

WebServiceHost的正确绑定值为webHttpBinding(也可能是ws

<endpoint address="" binding="webHttpBinding" contract="MySite.Common.Services.Web.IRDCService">

请注意,与basicHttpBinding相反,https似乎没有对应的webHttpsBinding对应对象,应改用安全模式传输。

答案 5 :(得分:0)

因此,在将服务部署到Windows Server 2016上的IIS 10并尝试导航到服务屏幕后,就遇到了这种确切的错误。

与之抗争了一段时间之后,我去添加了多个具有不同绑定的端点,以为它可能不像我正在使用的ws2007FederationHttpBinding。

这是原始端点配置:

<services>
  <service name="Vendor.Services.Provider.Host.Implementation.ProviderService">
    <endpoint
      address="https://svc01dev/Services/Provider/4/0/ProviderService.svc"
      binding="ws2007FederationHttpBinding" 
      bindingConfiguration="Vendor.Services.Provider.Contracts.ServiceContracts.IProviderService_ws2007FederationHttpBinding" 
      contract="Vendor.Services.Provider.Contracts.ServiceContracts.IProviderService"/>
  </service>
</services>

我从端点删除了该地址,准备尝试多端点服务:

<services>
  <service name="Vendor.Services.Provider.Host.Implementation.ProviderService">
    <endpoint
      binding="ws2007FederationHttpBinding" 
      bindingConfiguration="Vendor.Services.Provider.Contracts.ServiceContracts.IProviderService_ws2007FederationHttpBinding" 
      contract="Vendor.Services.Provider.Contracts.ServiceContracts.IProviderService"/>
  </service>
</services>

只是看会发生什么,我再次导航到服务屏幕,然后弹出它。没有更多的错误。我将对此进行更多研究,但是如果有人知道,我一定会听到的。