2010-10-14 4 views
1

У меня есть служба WCF, которая вызывает небольшую головную боль. Я трассировка включена, у меня есть объект с контрактом данных строится и прошло, но я вижу эту ошибку в журнале:WCF Service, возвращающий ошибку 400: тело сообщения не может быть прочитано, потому что оно пусто

<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 целочисленных свойства, я не могу себе представить, что это вызывает проблему.

+0

Поскольку я смотрю на это, мне интересно, является ли это запрос или ответ, который является проблемой. У меня есть трассировка сообщений, но ни один журнал не генерируется, что приводит меня к предположению, что именно запрос был проблемой, а не ответом. – Josh

+0

На стороне примечание, RulesException и все классы внутри сериализуемы, хотя он также имеет коллекцию IEnumberable как одно из ее свойств. – Josh

+0

Я просто исключил ответ, комментируя результаты и исключение. Он по-прежнему возвратил ошибку 400. – Josh

ответ

2

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

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

И вам нужно включить Microsoft .Net Framework 3.1 -> HTTP-активация связи Windows для добавления/удаления функций Windows.

открыть ваше командное окно Visual Studio

Затем вы должны запустить aspnet_regiis -i

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

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

+0

Mr @josh, пожалуйста, помогите мне решить мою проблему вроде этого и http://stackoverflow.com/questions/38856971/wcf-http-binding – Farshid

1

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

При возникновении проблемы с сервисом WCF и сбое или слишком занятой работе. эти проблемы возникают когда-то.

С уважением,

Mazhar Карего

2

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

1

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

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

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

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

Смежные вопросы