Skip to content

Commit

Permalink
To support soap encoded message. (#1885)
Browse files Browse the repository at this point in the history
* To support soap encoded message.
Exposed XmlSerializerOperationBehavior.GetXmlMappings.

Fix #1549.
Fix #1797.

* Fixed Issue with BasicHttpSoapTestServiceHostFactory.

* Add one more test for Soap.

* Refactor the tests.

* Change to use IssueAttribute.
  • Loading branch information
shmao authored May 5, 2017
1 parent 1a314cd commit 0961d82
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 88 deletions.
20 changes: 19 additions & 1 deletion src/System.Private.ServiceModel/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1932,4 +1932,22 @@
<data name="Xml_InvalidNodeType" xml:space="preserve">
<value>'{0}' is an invalid XmlNodeType.</value>
</data>
</root>
<data name="SFxRpcMessageMustHaveASingleBody" xml:space="preserve">
<value>RPC Message {1} in operation {0} must have a single MessageBodyMember.</value>
</data>
<data name="SFxBodyObjectTypeCannotBeInherited" xml:space="preserve">
<value>Type {0} cannot inherit from any class other than object to be used as body object in RPC style.</value>
</data>
<data name="SFxBodyObjectTypeCannotBeInterface" xml:space="preserve">
<value>Type {0} implements interface {1} which is not supported for body object in RPC style.</value>
</data>
<data name="SFxHeadersAreNotSupportedInEncoded" xml:space="preserve">
<value>Message {0} must not have headers to be used in RPC encoded style.</value>
</data>
<data name="SFxMultiplePartsNotAllowedInEncoded" xml:space="preserve">
<value>Part {1}:{0} is repeating and is not supported in Soap Encoding.</value>
</data>
<data name="SFxInvalidSoapAttribute" xml:space="preserve">
<value>XmlSerializer attribute {0} is not valid in {1}. Only SoapElement attribute is supported.</value>
</data>
</root>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public static string HttpBaseAddress_4_4_0_Basic
{
get { return GetEndpointAddress("BasicHttp_4_4_0.svc//Basic"); }
}

public static string HttpBaseAddress_Basic_Soap
{
get { return GetEndpointAddress("BasicHttpSoap.svc//Basic"); }
}

public static string HttpBaseAddress_NetHttp
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,41 @@ public int Id
}
}

public class SoapComplexType
{
private bool _boolValue;
private string _stringValue;

public bool BoolValue
{
get { return _boolValue; }
set { _boolValue = value; }
}

public string StringValue
{
get { return _stringValue; }
set { _stringValue = value; }
}
}

[SoapType(Namespace = "WcfService")]
public class CustomerObject
{
public string Name { get; set; }
public object Data { get; set; }
}

[Serializable]
[SoapType(Namespace = "WcfService")]
public partial class AdditionalData
{
public string Field
{
get; set;
}
}

// This type should be used by XmlSerializerFormat_EchoVeryComplexType only.
// The type should not ever be instantiated.
public class NonInstantiatedType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ public interface IWcfServiceXmlGenerated
XmlVeryComplexType EchoXmlVeryComplexType(XmlVeryComplexType complex);
}

[ServiceContract(ConfigurationName = "IWcfSoapService")]
public interface IWcfSoapService
{
[OperationContract(Action = "http://tempuri.org/IWcfService/CombineStringXmlSerializerFormatSoap", ReplyAction = "http://tempuri.org/IWcfService/CombineStringXmlSerializerFormatSoapResponse")]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, SupportFaults = true, Use = OperationFormatUse.Encoded)]
string CombineStringXmlSerializerFormatSoap(string message1, string message2);

[OperationContract(Action = "http://tempuri.org/IWcfService/EchoComositeTypeXmlSerializerFormatSoap", ReplyAction = "http://tempuri.org/IWcfService/EchoComositeTypeXmlSerializerFormatSoapResponse")]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, SupportFaults = true, Use = OperationFormatUse.Encoded)]
SoapComplexType EchoComositeTypeXmlSerializerFormatSoap(SoapComplexType c);

[OperationContract(Action = "http://tempuri.org/IWcfService/ProcessCustomerData", ReplyAction = "http://tempuri.org/IWcfSoapService/ProcessCustomerDataResponse")]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, SupportFaults = true, Use = OperationFormatUse.Encoded)]
[ServiceKnownType(typeof(AdditionalData))]
[return: MessageParameter(Name = "ProcessCustomerDataReturn")]
string ProcessCustomerData(CustomerObject CustomerData);
}

// This type share the same name space with IWcfServiceXmlGenerated.
// And this type contains a method which is also defined in IWcfServiceXmlGenerated.
[ServiceContract(ConfigurationName = "IWcfService")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading.Tasks;
using Infrastructure.Common;
using Xunit;
using System;

public static partial class XmlSerializerFormatTests
{
[WcfFact]
[OuterLoop]
public static void CombineString_XmlSerializerFormat_Soap()
{
RunWcfSoapServiceTest((serviceProxy) =>
{
// *** EXECUTE *** \\
string message1 = "hello";
string message2 = "world";
var response = serviceProxy.CombineStringXmlSerializerFormatSoap(message1, message2);

// *** VALIDATE *** \\
Assert.Equal(message1 + message2, response);
});
}

[WcfFact]
[OuterLoop]
[Issue(1884)]
public static void EchoComositeType_XmlSerializerFormat_Soap()
{
RunWcfSoapServiceTest((serviceProxy) =>
{
// *** EXECUTE *** \\
var value = new SoapComplexType() { BoolValue = true, StringValue = "hello" };
SoapComplexType response = serviceProxy.EchoComositeTypeXmlSerializerFormatSoap(value);

// *** VALIDATE *** \\
Assert.NotNull(response);
Assert.Equal(value.BoolValue, response.BoolValue);
Assert.Equal(value.StringValue, response.StringValue);
});
}

[WcfFact]
[OuterLoop]
public static void ProcessCustomerData_XmlSerializerFormat_Soap()
{
RunWcfSoapServiceTest((serviceProxy) =>
{
// *** EXECUTE *** \\
CustomerObject value = new CustomerObject() { Name = "MyName", Data = new AdditionalData() { Field = "Foo" } };
string response = serviceProxy.ProcessCustomerData(value);

// *** VALIDATE *** \\
Assert.Equal("MyNameFoo", response);
});
}

private static void RunWcfSoapServiceTest(Action<IWcfSoapService> testMethod)
{
BasicHttpBinding binding;
EndpointAddress endpointAddress;
ChannelFactory<IWcfSoapService> factory;
IWcfSoapService serviceProxy = null;

try
{
// *** SETUP *** \\
binding = new BasicHttpBinding();
endpointAddress = new EndpointAddress(Endpoints.HttpBaseAddress_Basic_Soap);
factory = new ChannelFactory<IWcfSoapService>(binding, endpointAddress);
serviceProxy = factory.CreateChannel();
testMethod(serviceProxy);

// *** CLEANUP *** \\
factory.Close();
((ICommunicationObject)serviceProxy).Close();
}
finally
{
// *** ENSURE CLEANUP *** \\
ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,39 @@ public override bool TryResolveType(Type type, Type declaredType, DataContractRe
return knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace);
}
}
}
}

public class SoapComplexType
{
private bool _boolValue;
private string _stringValue;

public bool BoolValue
{
get { return _boolValue; }
set { _boolValue = value; }
}

public string StringValue
{
get { return _stringValue; }
set { _stringValue = value; }
}
}

[SoapType(Namespace = "WcfService")]
public class CustomerObject
{
public string Name { get; set; }
public object Data { get; set; }
}

[Serializable]
[SoapType(Namespace = "WcfService")]
public partial class AdditionalData
{
public string Field
{
get; set;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


using System;
using System.ServiceModel;
using System.Threading.Tasks;

namespace WcfService
{
[ServiceContract]
[XmlSerializerFormat(Use = OperationFormatUse.Encoded)]
public interface IWcfSoapService
{
[OperationContract(Action = "http://tempuri.org/IWcfService/CombineStringXmlSerializerFormatSoap")]
[XmlSerializerFormat(Use = OperationFormatUse.Encoded)]
string CombineStringXmlSerializerFormatSoap(string message1, string message2);

[OperationContract(Action = "http://tempuri.org/IWcfService/EchoComositeTypeXmlSerializerFormatSoap")]
[XmlSerializerFormat(Use = OperationFormatUse.Encoded)]
SoapComplexType EchoComositeTypeXmlSerializerFormatSoap(SoapComplexType c);

[OperationContract(Action = "http://tempuri.org/IWcfService/ProcessCustomerData")]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, SupportFaults = true, Use = OperationFormatUse.Encoded)]
[ServiceKnownType(typeof(AdditionalData))]
[return: MessageParameter(Name = "ProcessCustomerDataReturn")]
[return: System.Xml.Serialization.SoapElement(DataType = "string")]
string ProcessCustomerData([MessageParameter(Name = "CustomerData")]CustomerObject customerData);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.Text;
using System.Xml.Serialization;

namespace WcfService
{
public class WcfSoapService : IWcfSoapService
{
public string CombineStringXmlSerializerFormatSoap(string message1, string message2)
{
return message1 + message2;
}

public SoapComplexType EchoComositeTypeXmlSerializerFormatSoap(SoapComplexType complexObject)
{
return complexObject;
}

[return: MessageParameter(Name = "ProcessCustomerDataReturn"), SoapElement(DataType = "string")]
public string ProcessCustomerData([MessageParameter(Name = "CustomerData")] CustomerObject customerData)
{
return customerData.Name + ((AdditionalData)customerData.Data).Field;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;

namespace WcfService
{
public class BasicHttpSoapTestServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var serviceHost = new BasicHttpSoapTestServiceHost(serviceType, baseAddresses);
return serviceHost;
}
}

public class BasicHttpSoapTestServiceHost : TestServiceHostBase<IWcfSoapService>
{
protected override string Address { get { return "Basic"; } }

protected override Binding GetBinding()
{
return new BasicHttpBinding();
}

public BasicHttpSoapTestServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<add factory="WcfService.BasicHttpsTestServiceHostFactory" service="WcfService.WcfService" relativeAddress="~\BasicHttps.svc" />
<add factory="WcfService.BasicHttpTestServiceHostFactory" service="WcfService.WcfService" relativeAddress="~\BasicHttp.svc" />
<add factory="WcfService.BasicHttpTestServiceHostFactory_4_4_0" service="WcfService.WcfService_4_4_0" relativeAddress="~\BasicHttp_4_4_0.svc" />
<add factory="WcfService.BasicHttpSoapTestServiceHostFactory" service="WcfService.WcfSoapService" relativeAddress="~\BasicHttpSoap.svc" />
<add factory="WcfService.ChannelExtensibilityServiceHostFactory" service="WcfService.WcfChannelExtensiblityService" relativeAddress="~\ChannelExtensibility.svc" />
<add factory="WcfService.CustomTextEncoderBufferedTestServiceFactory" service="WcfService.WcfService" relativeAddress="~\CustomTextEncoderBuffered.svc" />
<add factory="WcfService.CustomTextEncoderStreamedTestServiceFactory" service="WcfService.WcfService" relativeAddress="~\CustomTextEncoderStreamed.svc" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ private static void Main()
CreateHost<BasicAuthTestServiceHost, WcfUserNameService>("BasicAuth.svc", httpsBaseAddress);
CreateHost<BasicHttpsTestServiceHost, WcfService.WcfService>("BasicHttps.svc", httpsBaseAddress);
CreateHost<BasicHttpTestServiceHost, WcfService.WcfService>("BasicHttp.svc", httpBaseAddress);
CreateHost<BasicHttpTestServiceHost_4_4_0, WcfService_4_4_0>("BasicHttp_4_4_0.svc", httpBaseAddress);
CreateHost<BasicHttpTestServiceHost_4_4_0, WcfService_4_4_0>("BasicHttp_4_4_0.svc", httpBaseAddress);
CreateHost<BasicHttpSoapTestServiceHost, WcfSoapService>("BasicHttpSoap.svc", httpBaseAddress);
CreateHost<CustomTextEncoderBufferedTestServiceHost,WcfService.WcfService>("CustomTextEncoderBuffered.svc", httpBaseAddress);
CreateHost<CustomTextEncoderStreamedTestServiceHost, WcfService.WcfService>("CustomTextEncoderStreamed.svc", httpBaseAddress);
CreateHost<DefaultCustomHttpTestServiceHost, WcfService.WcfService>("DefaultCustomHttp.svc", httpBaseAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,7 @@ public partial class XmlSerializerOperationBehavior : System.ServiceModel.Descri
public XmlSerializerOperationBehavior(System.ServiceModel.Description.OperationDescription operation) { }
public XmlSerializerOperationBehavior(System.ServiceModel.Description.OperationDescription operation, System.ServiceModel.XmlSerializerFormatAttribute attribute) { }
public System.ServiceModel.XmlSerializerFormatAttribute XmlSerializerFormatAttribute { get { return default(System.ServiceModel.XmlSerializerFormatAttribute); } }
public System.Collections.ObjectModel.Collection<System.Xml.Serialization.XmlMapping> GetXmlMappings() { throw null; }
void System.ServiceModel.Description.IOperationBehavior.Validate(System.ServiceModel.Description.OperationDescription description) { }
void System.ServiceModel.Description.IOperationBehavior.AddBindingParameters(System.ServiceModel.Description.OperationDescription description, System.ServiceModel.Channels.BindingParameterCollection parameters) { }
void System.ServiceModel.Description.IOperationBehavior.ApplyDispatchBehavior(System.ServiceModel.Description.OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch) { }
Expand Down

0 comments on commit 0961d82

Please sign in to comment.