Служба WCF, возвращающая ошибку 400: тело сообщения не может быть прочитано, потому что оно пустое - PullRequest
1 голос
/ 14 октября 2010

У меня есть служба 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);
        }
    }

Конфигурация для веб-службы (на стороне сервера) выглядит следующим образом:

<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 ]

2 голосов
/ 02 июня 2014

Я столкнулся с той же проблемой, но вызванной другой проблемой.

Я реализовал свой собственный хост службы для службы WCF REST и случайно вывел свой класс из System.ServiceModel.ServiceHost вместо System.ServiceModel.Web.WebServiceHost

Я мог бы активировать службу, перейдя к корневому URL, но когда я попытался получить доступ к одному из открытых ресурсов, я получил бы ошибку HTTP 400. Подключение отладчика показало исключение, упомянутое выше.

Надеюсь, это когда-нибудь кому-нибудь поможет.

2 голосов
/ 21 июня 2013

У меня была та же проблема, по-видимому, она была вызвана косой чертой в конце .svc в URL. Не ставьте косую черту там ... и это сработало.

2 голосов
/ 14 октября 2010

Если вы столкнулись с этой проблемой, вам нужно запустить приложение WCF на локальном IIS.

Перейдите в Свойства для проекта приложения wcf и выберите «Использовать локальный веб-сервер iis».

И вам нужно активировать Microsoft .Net Framework 3.1 -> активация Windows Communication Foundation http в функции добавления / удаления окон.

открыть окно командной строки visual studio

Затем необходимо запустить aspnet_regiis-i

И вам нужно запустить servicemodelreg -ia

Это было много, запустите это, получите ошибку, выполните поиск в Google, промойте, повторите.Потребовалось около часа, чтобы все выяснить.PITA.

1 голос
/ 27 октября 2010

У нас была одна и та же проблема много раз, пожалуйста, разместите на IIS, она намного лучше в отношении производительности и масштабируемости.

Когда есть проблема в службе WCF, и она падает или слишком занята. эта проблема возникает когда-то.

С уважением,

Мажар Карими

0 голосов
/ 30 апреля 2019

Так что просто столкнулся с этой точной ошибкой после развертывания службы в IIS 10 на Windows Server 2016 и попытки перейти к экрану службы.

Поработав с ним некоторое время, я решил добавить несколько конечных точек с разными привязками, думая, что это может не понравиться привязке 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>

Просто чтобы посмотреть, что произойдет, я снова перешел на экран службы, и он выскочилвверх.Нет больше ошибок.Я собираюсь разобраться в этом еще немного, но если кто-нибудь знает, я бы хотел это услышать.

0 голосов
/ 17 августа 2018

То же сообщение об ошибке было вызвано привязкой конечной точки, установленной на basicHttpBinding в App.config (даже если System.ServiceModel.Web.WebServiceHost использовался в качестве ответа @ MvdD):

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

правильное значение привязки для WebServiceHost is webHttpBinding (возможно, также ws)

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

обратите внимание, в отличие от basicHttpBinding, похоже, что не существует соответствующего webHttpsBinding аналога для https, транспорт в режиме безопасности должен бытьиспользуется вместо.

...