Can a WCF operation that uses a single array as a parameter use MessageContracts?

I am trying to replace asmx WebService with a WCF service. My main goal is to keep the SOAP message the same. The caller is not .NET and requires significant overhaul to make minor changes to the contract.

My pain is that the web methods that I'm trying to replace the webmethod use the following attribute braking:

[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)] 

This removes an extra layer of XML elements around each parameter.

The only way I can mimic this with WCF is to use MessageContracts instead of DataContracts and use the WrappedName and IsWrapped property to control the formatting of the parameters.

This approach works for all my methods except one, which takes as a parameter one array of the POCO object.

My conclusion is that I have no options. I cannot update this web service and maintain the same contract.

My questions:

1) The only way to replicate:

  [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)] 

on a web method in WCF to use MessageContract?

2) And is there a way for a method to take a single array as a parameter?

Here is a simple example that I worked with to show what I see / Do with [SoapDocumentMethod (ParameterStyle = SoapParameterStyle.Bare)] and Message Contract

Support Code:

 using System.Web.Services; using System.Web.Services.Protocols; using System.ServiceModel; namespace WebApplication1{ /// <summary> /// The Service Contract /// </summary> [ServiceContract] public interface ISimpleMathService { [OperationContract()] AddResp Add(AddReq add); } /// <summary> /// The Service Implementation /// </summary> public class simpleMath : ISimpleMathService { [WebMethod()] //Allows the Service to be exposed as a asmx Service [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)] public AddResp Add(AddReq add) { return new AddResp {result = add.NumOne + add.NumTwo}; } } } 

POCO Objects: (V1 with Data Contracts)

  using System.Runtime.Serialization; using System.ServiceModel; namespace WebApplication1 { [DataContract] public class AddReq { [DataMember] public int NumOne { get; set; } [DataMember] public int NumTwo { get; set; } } [DataContract] public class AddResp { [DataMember] public int result{ get; set; } } } 

ASMX SOAP

 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/"> <soapenv:Header/> <soapenv:Body> <tem:add> <tem:NumOne>12</tem:NumOne> <tem:NumTwo>12</tem:NumTwo> </tem:add> </soapenv:Body> </soapenv:Envelope> 

SOAP request with WCF data contract

 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:web="http://schemas.datacontract.org/2004/07/WebApplication1"> <soap:Header/> <soap:Body> <tem:Add> <tem:add> <web:NumOne>10</web:NumOne> <web:NumTwo>10</web:NumTwo> </tem:add> </tem:Add> </soap:Body> </soap:Envelope> 

Allows the use of Message Contracts in our arguments and return types: POCO Objects: (V2 with MessageContracts)

 namespace WebApplication1 { [DataContract] [MessageContract(WrapperName="add", IsWrapped = true)] //Default Wrapper Name is "Add", not add public class AddReq { [DataMember] [MessageBodyMember] public int NumOne { get; set; } [DataMember] [MessageBodyMember] public int NumTwo { get; set; } } [DataContract] [MessageContract(IsWrapped = true)] public class AddResp { [DataMember] [MessageBodyMember] public int result{ get; set; } } } 

Soap request WCF (V2):

 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/"> <soap:Header/> <soap:Body> <tem:add> <tem:NumOne>19</tem:NumOne> <tem:NumTwo>12</tem:NumTwo> </tem:add> </soap:Body> </soap:Envelope> 

Here is what I am doing now, which corresponds to 90% of what I need.

The problem is that I would like to implement such a method in WCF and keep the contract the same:

 [WebMethod()] [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)] public AddResp AddArrays(AddReq [] addInput) { AddResp resp= new AddResp{result=0} foreach (var addrequest in addInput) { resp.result += (addrequest.NumOne + addrequest.NumTwo); } return resp; } 

When I do this now, I get the following exception because AddReq [] is not a MessageContract. AddReq [] is of type System.Array, which I cannot change.

The AddArrays operation cannot be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use other types of parameters.

Thanks Brian

+4
source share
2 answers

Turns out you can add a β€œHost Class” with IsWrapped = false and it works.

From the sample in the original question Here is what the wrapper class looks like:

 [DataContract,MessageContract(IsWrapped=false)] public class AddArraysReq { [DataMember] [MessageBodyMember] public AddReq[] AddReqs; } 

And it will look like this:

  public AddResp AddArrays(AddArraysReq addInput) { AddResp resp = new AddResp {result = 0}; foreach (var addrequest in addInput.AddReqs) { resp.result += (addrequest.NumOne + addrequest.NumTwo); } return resp; } 

Received SOAP request:

 <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:web="http://schemas.datacontract.org/2004/07/WebApplication1"> <soap:Header/> <soap:Body> <tem:AddReqs> <web:AddReq> <web:NumOne>10</web:NumOne> <web:NumTwo>10</web:NumTwo> </web:AddReq> <web:AddReq> <web:NumOne>10</web:NumOne> <web:NumTwo>10</web:NumTwo> </web:AddReq> </tem:AddReqs> </soap:Body> </soap:Envelope> 

I did not understand that IsWrapped = false removed the entire repetition of the class from the request.

+2
source

I'm a little puzzled by your statement that SoapParameterStyle.Bare removes the XML layer around the parameters, but you can only replicate it with contracts with the message IsWrapped=true , which in turn basically adds an XML wrapper around the SOAP payload again ... seems a bit controversial.

Can you show us a web method declaration for your method that takes an array of POCOs as a parameter? What have you tried in WCF? Typically, with BasicHttpBinding and with almost no options, you are very close to what ASMX did in the old days.

+1
source

Source: https://habr.com/ru/post/1303289/


All Articles