Служба WCF - вызов клиента для доступа к остальным с использованием json не дает правильный тип содержимого - PullRequest
0 голосов
/ 05 марта 2012

У меня есть проблема (из-за которой я вырывал свои волосы в течение нескольких дней), из-за которой я пытаюсь использовать службу WCF для вызова другой службы RESTful.

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

пример вызова в клиенте (это внутри службы WCF, которая вызывает код)

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior()]
public partial class MyRestServiceClient : System.ServiceModel.ClientBase<IMyRestService>, IMyRestService
{
    [WebInvoke(Method = "POST", UriTemplate = "/MyService/ReferenceTypes.json", RequestFormat = WebMessageFormat.Json)]
    public MyServiceLists GetReferenceTypes()
    {
        try
        {
            return base.Channel.GetReferenceTypes();
        }
        catch (Exception e)
        {
            throw e; //throws exception here - method not allowed 
        }
    }
}

Вместо того, чтобы помещать тип контента application / json, он помещает application / xml вместо вызова. это было получено из трассировки активности, помещенной в службу WCF, выполняющую вызов. пример информации "сообщение отправлено" из журнала активности:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>262164</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2012-03-05T12:26:52.8913972Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{7759c13c-972d-46a2-8048-2dcaf1c066bf}" />
<Execution ProcessName="aspnet_wp" ProcessID="2408" ThreadID="11" />
<Channel />
<Computer>Z1020734</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Information">
<TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.Channels.MessageSent.aspx</TraceIdentifier>
<Description>Sent a message over a channel.</Description>
<AppDomain>/LM/w3svc/1/ROOT/My.Services-2-129754240054859056</AppDomain>
<Source>System.ServiceModel.Channels.HttpOutput+WebRequestHttpOutput/18905726</Source>
<ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/MessageTraceRecord">
<MessageProperties>
**<Encoder>application/xml; charset=utf-8</Encoder>**
<AllowOutputBatching>False</AllowOutputBatching>
<Via>http://mymachine/My.services.stub.REST/</Via>
</MessageProperties>
<MessageHeaders></MessageHeaders>
</ExtendedData>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>

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

конечная точка клиента указывает на службу Restful (с использованием шаблона Rest 40) на том же компьютере. см. ниже файл web.config службы WCf, которая пытается вызвать конечную точку Rest:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
  </connectionStrings>
  <appSettings>
  </appSettings>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  <system.serviceModel>
    <serviceHostingEnvironment  multipleSiteBindingsEnabled="true"/>
    <services>
      <service name="My.Services.MyService" behaviorConfiguration="My.Services.MyServiceBehavior" >
        <endpoint address="" binding="customBinding" bindingConfiguration="CustomBinding_IMyService" contract="My.Common.ServiceContracts.IMyService"/>
       </service>
      <service name="My.Services.SomeOtherService" behaviorConfiguration="My.Services.SomeOtherBehavior" >
        <endpoint address="" binding="customBinding"  bindingConfiguration="customBinding_ISomeOtherService" contract="My.Common.ServiceContracts.ISomeOtherService"/>
      </service>
    </services>
    <bindings>
      <webHttpBinding>
        <binding name="webHttpCustomBinding">
          <security mode="TransportCredentialOnly">
            <transport proxyCredentialType="None" clientCredentialType="Windows">
            </transport>
          </security>
        </binding>
      </webHttpBinding>

      <customBinding>
        <binding name ="CustomBinding_IIMyRestService">
           <webMessageEncoding webContentTypeMapperType="My.Common.ServiceModel.JsonContentTypeMapper, My.Common" ></webMessageEncoding>
          <httpTransport  authenticationScheme="Negotiate" ></httpTransport>
         </binding>
        <binding name="CustomBinding_IMyService">
          <textMessageEncoding messageVersion="Soap12" />
          <httpTransport maxBufferPoolSize="1000000" maxReceivedMessageSize="1000000"
            authenticationScheme="Negotiate" maxBufferSize="1000000"   />
        </binding>
        <binding name="customBinding_ISomeOtherService">
          <textMessageEncoding messageVersion="Soap12" />
          <httpTransport  />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://MyMachine/My.services.stub.REST/" binding="customBinding" bindingConfiguration="CustomBinding_IMyRestService" name="RestService" contract="My.Common.ServiceContracts.IIMyRestService" behaviorConfiguration="webhttp"/>
 </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webhttp">
        </behavior>
 </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="My.Services.MyServiceBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="My.Services.SomeOtherServiceBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <system.net>
    <defaultProxy useDefaultCredentials="true"/>
  </system.net>
 <system.diagnostics>
    <trace autoflush="true"/>
    <sources>
      <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\temp\my.Services.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics> 
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
</configuration>

Примечание: консольное приложение, которое я написал с той же функцией и настройкой, работает правильно и выдает правильный тип контента.

Любая помощь, которую вы можете оказать, приветствуется.

1 Ответ

2 голосов
/ 19 октября 2012

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

Подробности можно посмотреть здесь: Клиент WCF Rest отправляет неверный тип контента

...