JSON and SOAP WCF Service?

2019-07-01 20:12发布

I recently converted a WCF SOAP service into REST/JSON service. As detailed in the response here, the Add Service Reference feature of Visual Studio is incapable of generating code for a JSON service. The linked article in that question's answer alludes to the possibility of having a WCF exposed as both REST and SOAP to solve the issue, but it doesn't give any details how to do so.

Does anyone know if this is possible and if so, how to set it up?

There's always the alternative of writing a code generator myself, which reads the WSDL for the WCF REST service and generates C# classes, but it seems like there should be an easier solution than this.

For reference, My web.config:

<system.serviceModel>
<behaviors>
  <endpointBehaviors>
    <behavior name="RestBehavior">
      <webHttp />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="GetBehavior" >
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug
         httpHelpPageEnabled="true"
         includeExceptionDetailInFaults="true"
      />
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
  <webHttpBinding>
    <binding name="WebHttpBinding">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="None" />
      </security>
    </binding>
  </webHttpBinding>
</bindings>
<services>
  <service name="Service" behaviorConfiguration="GetBehavior">
    <endpoint address=""
      binding="webHttpBinding"
      behaviorConfiguration="RestBehavior"
      contract="IService"
      bindingConfiguration="WebHttpBinding">
    </endpoint>
  </service>
</services>
</system.serviceModel>

My service methods all have the following attribute:

[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]

2条回答
看我几分像从前
2楼-- · 2019-07-01 20:22

It is possible, you need to create two endpoints: one for soap, other for json. I have done that in my project, and can access service at same time via SoapUI or Fiddler (json), here is example config:

<system.serviceModel>
 <behaviors>
  <serviceBehaviors>
   <behavior name="BehaviourService">
    <serviceMetadata httpGetEnabled="true" />
     <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
      <behavior name="BehaviourWebHttp">
        <webHttp  defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="True" faultExceptionEnabled="True" />
      </behavior>
  </endpointBehaviors>
</behaviors>

<services>
  <service name="NameSpace.MyService" behaviorConfiguration="BehaviourService" >
    <endpoint address ="soap" binding="basicHttpBinding" contract="NameSpace.IMyService"></endpoint>
    <endpoint binding="webHttpBinding" behaviorConfiguration="BehaviourWebHttp" contract="NameSpace.IMyService" ></endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:7689/MyService.svc"/>
      </baseAddresses>
    </host>
  </service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

Also make your contracts look like:

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "MyMethod", Method = "POST")]
bool MyMethod();

Then you can accees SOAP via "localhost:7689/MyService.svc?wsdl" and JSON via "localhost:7689/MyService.svc/MyMethod"

查看更多
闹够了就滚
3楼-- · 2019-07-01 20:39

As far as I know you have three options for combining json and xml responses from WCF and neither of them are desirable:

  1. Write specific methods (and enpoints) for XML and JSON and decorate them accordingly
  2. Hook into the serialization engine and combine this with an inspection of the accept header from the http request.
  3. Let your method accept and return a Stream which by convention tells WCF to give you direct access to the request and response streams.

Each method has it's own flaws: 1. This is ugly and contrary to the ideas of Rest, since the serialization should be determined using http headers, not the URL (which should identify the resource). 2. It is complicated to attach to the serialization engine and you still need to look at the headers to determine the serialization. 3. You get no help in mapping request parameters and the serialization clutters you method body.

I have been using method 3 on many occasions because it is simple and easy to get started with, but method 2 seems to be more correct.

查看更多
登录 后发表回答