Skip to content

Commit

Permalink
Merge pull request #786 from DigDes/develop
Browse files Browse the repository at this point in the history
v1.1.0.23
  • Loading branch information
kotovaleksandr authored Dec 20, 2021
2 parents 6e122e1 + cbf7428 commit 6834c3f
Show file tree
Hide file tree
Showing 17 changed files with 348 additions and 124 deletions.
30 changes: 30 additions & 0 deletions src/SoapCore.Tests/MessageContract/Models/IArrayOfIntService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;

namespace SoapCore.Tests.MessageContract.Models
{
[ServiceContract(Namespace = "http://tempuri.org")]
public interface IArrayOfIntService
{
[OperationContract]
int[] ArrayOfIntMethod(int[] arrayOfIntParam);

[OperationContract]
int IntMethod(int intParam);
}

public class ArrayOfIntService : IArrayOfIntService
{
public int[] ArrayOfIntMethod(int[] arrayOfIntParam)
{
return arrayOfIntParam;
}

public int IntMethod(int intParam)
{
return intParam;
}
}
}
51 changes: 51 additions & 0 deletions src/SoapCore.Tests/MessageContract/RawRequestSoap11Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,57 @@ public async Task Soap11MessageContractNotWrapped()
}
}

[TestMethod]
public async Task Soap11MessageContractArrayOfIntParam()
{
const string body = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org"">
<soapenv:Header/>
<soapenv:Body>
<tem:ArrayOfIntMethod>
<tem:arrayOfIntParam>1,2</tem:arrayOfIntParam>
</tem:ArrayOfIntMethod>
</soapenv:Body>
</soapenv:Envelope>
";

using (var host = CreateTestHost(typeof(ArrayOfIntService)))
using (var client = host.CreateClient())
using (var content = new StringContent(body, Encoding.UTF8, "text/xml"))
using (var res = await host.CreateRequest("/Service.asmx").AddHeader("SOAPAction", @"""ArrayOfIntMethod""").And(msg => msg.Content = content).PostAsync())
{
res.EnsureSuccessStatusCode();
var resultMessage = await res.Content.ReadAsStringAsync();

//the result should be an empty array
Assert.IsTrue(resultMessage.Contains("<ArrayOfIntMethodResult />"));
}
}

[TestMethod]
public async Task Soap11MessageContractArrayOfIntParamWrapped()
{
const string body2 = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org"">
<soapenv:Header/>
<soapenv:Body>
<tem:ArrayOfIntMethod>
<tem:arrayOfIntParam><tem:int>1</tem:int><tem:int>2</tem:int></tem:arrayOfIntParam>
</tem:ArrayOfIntMethod>
</soapenv:Body>
</soapenv:Envelope>
";

using (var host = CreateTestHost(typeof(ArrayOfIntService)))
using (var client = host.CreateClient())
using (var content = new StringContent(body2, Encoding.UTF8, "text/xml"))
using (var res = await host.CreateRequest("/Service.asmx").AddHeader("SOAPAction", @"""ArrayOfIntMethod""").And(msg => msg.Content = content).PostAsync())
{
res.EnsureSuccessStatusCode();
var resultMessage = await res.Content.ReadAsStringAsync();
Assert.IsTrue(resultMessage.Contains("<int>1</int>"));
Assert.IsTrue(resultMessage.Contains("<int>2</int>"));
}
}

[TestMethod]
public async Task Soap11MessageContractComplexNotWrapped()
{
Expand Down
4 changes: 4 additions & 0 deletions src/SoapCore.Tests/Serialization/Models.Xml/ISampleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ NotWrappedFieldComplexInputResponse NotWrappedFieldDoubleComplexInputRequestMeth
[XmlSerializerFormat(SupportFaults = true)]
MessageContractResponseWithArrays TestMessageContractWithArrays(MessageContractRequestWithArrays request);

[OperationContract(Action = ServiceNamespace.Value + nameof(TestMessageContractWithWithRpcStyle), ReplyAction = "*")]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, Use = OperationFormatUse.Encoded, SupportFaults = false)]
MessageContractResponseRpcStyle TestMessageContractWithWithRpcStyle(MessageContractRequestRpcStyle request);

[OperationContract(Action = ServiceNamespace.Value + nameof(EnumMethod), ReplyAction = "*")]
[XmlSerializerFormat(SupportFaults = true)]
bool EnumMethod(out SampleEnum e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace SoapCore.Tests.Serialization.Models.Xml
{
[System.ServiceModel.MessageContract(WrapperName = "TestMessageContractWithWithRpcStyle", WrapperNamespace = "http://xmlelement-namespace/", IsWrapped = true)]
public class MessageContractRequestRpcStyle
{
[System.ServiceModel.MessageBodyMember(Namespace = "", Order = 0)]
public string StringParameter { get; set; }

[System.ServiceModel.MessageBodyMember(Namespace = "", Order = 1)]
public int IntParameter { get; set; }

[System.ServiceModel.MessageBodyMember(Namespace = "", Order = 2)]
public SampleEnum EnumParameter { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace SoapCore.Tests.Serialization.Models.Xml
{
[System.ServiceModel.MessageContract(WrapperName = "TestMessageContractWithWithRpcStyleResponse", WrapperNamespace = "http://xmlelement-namespace/", IsWrapped = true)]
public class MessageContractResponseRpcStyle
{
[System.ServiceModel.MessageBodyMember(Namespace = "", Order = 0)]
public int Result { get; set; }

[System.ServiceModel.MessageBodyMember(Namespace = "", Order = 1)]
public string Message { get; set; }
}
}
29 changes: 29 additions & 0 deletions src/SoapCore.Tests/Serialization/XmlSerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,35 @@ public void TestMessageContractWithArrays(SoapSerializer soapSerializer)
pingComplexModelResult_client.ShouldDeepEqual(MessageContractResponseWithArrays.CreateSample());
}

[Theory]
[InlineData(SoapSerializer.XmlSerializer)]
public void TestMessageContractWithRpcStyle_RequestParametersAreNotNull(SoapSerializer soapSerializer)
{
var serviceClient = _fixture.GetSampleServiceClient(soapSerializer);

var request = new MessageContractRequestRpcStyle { StringParameter = "abc", IntParameter = 14, EnumParameter = SampleEnum.C };
var expectedResponse = new MessageContractResponseRpcStyle { Result = 17, Message = "Ok" };

_fixture.ServiceMock
.Setup(x => x.TestMessageContractWithWithRpcStyle(It.IsAny<MessageContractRequestRpcStyle>()))
.Callback(
(MessageContractRequestRpcStyle actualRequest) =>
{
// check that incoming request is not null, and all properties are filled
Assert.NotNull(actualRequest);
Assert.Equal("abc", actualRequest.StringParameter);
Assert.Equal(14, actualRequest.IntParameter);
Assert.Equal(SampleEnum.C, actualRequest.EnumParameter);
})
.Returns(expectedResponse);

var response = serviceClient.TestMessageContractWithWithRpcStyle(request);

Assert.NotNull(response);
Assert.Equal(17, response.Result);
Assert.Equal("Ok", response.Message);
}

[Theory]
[InlineData(SoapSerializer.XmlSerializer)]
public void TestPingComplexArrayModel(SoapSerializer soapSerializer)
Expand Down
35 changes: 32 additions & 3 deletions src/SoapCore.Tests/Wsdl/WsdlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,38 @@ namespace SoapCore.Tests.Wsdl
public class WsdlTests
{
private readonly XNamespace _xmlSchema = "http://www.w3.org/2001/XMLSchema";
private readonly XNamespace _wsdlSchema = "http://schemas.xmlsoap.org/wsdl/";

private IWebHost _host;

[TestMethod]
public async Task CheckBindingAndPortName()
{
var wsdl = await GetWsdlFromMetaBodyWriter<TaskNoReturnService>(SoapSerializer.XmlSerializer, "MyBinding", "MyPort");
var root = XElement.Parse(wsdl);

// We should have in the wsdl the definition of a complex type representing the nullable enum
var bindingElements = GetElements(root, _wsdlSchema + "binding").Where(a => a.Attribute("name")?.Value.Equals("MyBinding") == true).ToArray();
bindingElements.ShouldNotBeEmpty();

var portElements = GetElements(root, _wsdlSchema + "port").Where(a => a.Attribute("name")?.Value.Equals("MyPort") == true).ToArray();
portElements.ShouldNotBeEmpty();
}

[TestMethod]
public async Task CheckDefaultBindingAndPortName()
{
var wsdl = await GetWsdlFromMetaBodyWriter<TaskNoReturnService>(SoapSerializer.XmlSerializer);
var root = XElement.Parse(wsdl);

// We should have in the wsdl the definition of a complex type representing the nullable enum
var bindingElements = GetElements(root, _wsdlSchema + "binding").Where(a => a.Attribute("name")?.Value.Equals("BasicHttpBinding_soap") == true).ToArray();
bindingElements.ShouldNotBeEmpty();

var portElements = GetElements(root, _wsdlSchema + "port").Where(a => a.Attribute("name")?.Value.Equals("BasicHttpBinding_soap") == true).ToArray();
portElements.ShouldNotBeEmpty();
}

[TestMethod]
public void CheckTaskReturnMethod()
{
Expand Down Expand Up @@ -734,15 +763,15 @@ private string GetWsdlFromAsmx()
}
}

private async Task<string> GetWsdlFromMetaBodyWriter<T>(SoapSerializer serializer)
private async Task<string> GetWsdlFromMetaBodyWriter<T>(SoapSerializer serializer, string bindingName = null, string portName = null)
{
var service = new ServiceDescription(typeof(T));
var baseUrl = "http://tempuri.org/";
var xmlNamespaceManager = Namespaces.CreateDefaultXmlNamespaceManager();
var bodyWriter = serializer == SoapSerializer.DataContractSerializer
? new MetaWCFBodyWriter(service, baseUrl, "BasicHttpBinding", false) as BodyWriter
: new MetaBodyWriter(service, baseUrl, xmlNamespaceManager, "BasicHttpBinding", new[] { MessageVersion.None }) as BodyWriter;
var encoder = new SoapMessageEncoder(MessageVersion.Soap12WSAddressingAugust2004, System.Text.Encoding.UTF8, XmlDictionaryReaderQuotas.Max, false, true, false);
: new MetaBodyWriter(service, baseUrl, xmlNamespaceManager, "BasicHttpBinding", new[] { new SoapBindingInfo(MessageVersion.None, bindingName, portName) }) as BodyWriter;
var encoder = new SoapMessageEncoder(MessageVersion.Soap12WSAddressingAugust2004, System.Text.Encoding.UTF8, XmlDictionaryReaderQuotas.Max, false, true, false, null, bindingName, portName);
var responseMessage = Message.CreateMessage(encoder.MessageVersion, null, bodyWriter);
responseMessage = new MetaMessage(responseMessage, service, xmlNamespaceManager, "BasicHttpBinding", false);

Expand Down
14 changes: 12 additions & 2 deletions src/SoapCore/MessageEncoder/SoapMessageEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ public class SoapMessageEncoder
private readonly bool _supportXmlDictionaryReader;
private readonly bool _checkXmlCharacters;

public SoapMessageEncoder(MessageVersion version, Encoding writeEncoding, XmlDictionaryReaderQuotas quotas, bool omitXmlDeclaration, bool indentXml, bool checkXmlCharacters)
public SoapMessageEncoder(MessageVersion version, Encoding writeEncoding, XmlDictionaryReaderQuotas quotas, bool omitXmlDeclaration, bool indentXml, bool checkXmlCharacters, XmlNamespaceManager xmlNamespaceOverrides, string bindingName, string portName)
{
_indentXml = indentXml;
_omitXmlDeclaration = omitXmlDeclaration;
_checkXmlCharacters = checkXmlCharacters;
BindingName = bindingName;
PortName = portName;

if (writeEncoding == null)
{
throw new ArgumentNullException(nameof(writeEncoding));
Expand All @@ -53,8 +56,13 @@ public SoapMessageEncoder(MessageVersion version, Encoding writeEncoding, XmlDic
MediaType = GetMediaType(version);
CharSet = SoapMessageEncoderDefaults.EncodingToCharSet(writeEncoding);
ContentType = GetContentType(MediaType, CharSet);

XmlNamespaceOverrides = xmlNamespaceOverrides;
}

public string BindingName { get; }
public string PortName { get; }

public string ContentType { get; }

public string MediaType { get; }
Expand All @@ -65,6 +73,8 @@ public SoapMessageEncoder(MessageVersion version, Encoding writeEncoding, XmlDic

public XmlDictionaryReaderQuotas ReaderQuotas { get; }

public XmlNamespaceManager XmlNamespaceOverrides { get; }

public bool IsContentTypeSupported(string contentType, bool checkCharset)
{
if (contentType == null)
Expand Down Expand Up @@ -129,7 +139,7 @@ public Task<Message> ReadMessageAsync(Stream stream, int maxSizeOfHeaders, strin

XmlReader reader = _supportXmlDictionaryReader ?
XmlDictionaryReader.CreateTextReader(stream, _writeEncoding, ReaderQuotas, dictionaryReader => { }) :
XmlReader.Create(stream, new XmlReaderSettings());
XmlReader.Create(stream, new XmlReaderSettings() { IgnoreWhitespace = true, DtdProcessing = DtdProcessing.Prohibit });

Message message = Message.CreateMessage(reader, maxSizeOfHeaders, MessageVersion);

Expand Down
54 changes: 27 additions & 27 deletions src/SoapCore/Meta/MetaBodyWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public class MetaBodyWriter : BodyWriter
private readonly HashSet<string> _buildArrayTypes;
private readonly Dictionary<string, Dictionary<string, string>> _requestedDynamicTypes;

private readonly HashSet<int> _soapVersions;

private bool _buildDateTimeOffset;

[Obsolete]
Expand All @@ -42,11 +40,11 @@ public MetaBodyWriter(ServiceDescription service, string baseUrl, Binding bindin
baseUrl,
xmlNamespaceManager ?? new XmlNamespaceManager(new NameTable()),
binding?.Name ?? "BasicHttpBinding_" + service.GeneralContract.Name,
new[] { binding.MessageVersion ?? MessageVersion.None })
new[] { new SoapBindingInfo(binding.MessageVersion ?? MessageVersion.None, null, null) })
{
}

public MetaBodyWriter(ServiceDescription service, string baseUrl, XmlNamespaceManager xmlNamespaceManager, string bindingName, MessageVersion[] messageVersions) : base(isBuffered: true)
public MetaBodyWriter(ServiceDescription service, string baseUrl, XmlNamespaceManager xmlNamespaceManager, string bindingName, SoapBindingInfo[] soapBindings) : base(isBuffered: true)
{
_service = service;
_baseUrl = baseUrl;
Expand All @@ -59,24 +57,14 @@ public MetaBodyWriter(ServiceDescription service, string baseUrl, XmlNamespaceMa
_builtComplexTypes = new HashSet<string>();
_buildArrayTypes = new HashSet<string>();
_requestedDynamicTypes = new Dictionary<string, Dictionary<string, string>>();
_soapVersions = new HashSet<int>();

BindingName = bindingName;
PortName = bindingName;
SoapBindings = soapBindings;

foreach (var messageVersion in messageVersions)
{
if (messageVersion == MessageVersion.Soap12WSAddressing10 || messageVersion == MessageVersion.Soap12WSAddressingAugust2004)
{
_soapVersions.Add(12);
}
else
{
_soapVersions.Add(11);
}
}
}

private SoapBindingInfo[] SoapBindings { get; }
private string BindingName { get; }
private string BindingType => _service.GeneralContract.Name;
private string PortName { get; }
Expand Down Expand Up @@ -215,9 +203,20 @@ private static bool TryGetMessageContractBodyMemberInfo(Type type, out MemberInf
return true;
}

private static (string name, string ns) GetSoapNameAndNamespace(int soapVersion)
private (string soapPrefix, string ns, string qualifiedBindingName, string qualifiedPortName) GetSoapMetaParameters(SoapBindingInfo bindingInfo)
{
return soapVersion == 12 ? ("soap12", Namespaces.SOAP12_NS) : ("soap", Namespaces.SOAP11_NS);
int soapVersion = 11;
if (bindingInfo.MessageVersion == MessageVersion.Soap12WSAddressingAugust2004 || bindingInfo.MessageVersion == MessageVersion.Soap12WSAddressing10)
{
soapVersion = 12;
}

(var soapPrefix, var ns) = soapVersion == 12 ? ("soap12", Namespaces.SOAP12_NS) : ("soap", Namespaces.SOAP11_NS);

var qualifiedBindingName = !string.IsNullOrWhiteSpace(bindingInfo.BindingName) ? bindingInfo.BindingName : (BindingName + $"_{soapPrefix}");
var qualifiedPortName = !string.IsNullOrWhiteSpace(bindingInfo.PortName) ? bindingInfo.PortName : (PortName + $"_{soapPrefix}");

return (soapPrefix, ns, qualifiedBindingName, qualifiedPortName);
}

private XmlQualifiedName ResolveType(Type type)
Expand Down Expand Up @@ -637,14 +636,14 @@ private void AddPortType(XmlDictionaryWriter writer)

private void AddBinding(XmlDictionaryWriter writer)
{
foreach (var soapVersion in _soapVersions)
foreach (var bindingInfo in SoapBindings)
{
(var soap, var soapNamespace) = GetSoapNameAndNamespace(soapVersion);
(var soap, var soapNamespace, var qualifiedBindingName, _) = GetSoapMetaParameters(bindingInfo);

writer.WriteStartElement("wsdl", "binding", Namespaces.WSDL_NS);
writer.WriteAttributeString("name", BindingName + $"_{soap}");
writer.WriteAttributeString("name", qualifiedBindingName);
writer.WriteAttributeString("type", "tns:" + BindingType);
writer.WriteAttributeString("style", "document");

writer.WriteStartElement(soap, "binding", soapNamespace);
writer.WriteAttributeString("transport", Namespaces.TRANSPORT_SCHEMA);
writer.WriteEndElement(); // soap:binding
Expand Down Expand Up @@ -686,15 +685,16 @@ private void AddService(XmlDictionaryWriter writer)
writer.WriteStartElement("wsdl", "service", Namespaces.WSDL_NS);
writer.WriteAttributeString("name", _service.ServiceName);

foreach (var soapVersion in _soapVersions)
foreach (var bindingInfo in SoapBindings)
{
(string soapName, string soapNamespace) = GetSoapNameAndNamespace(soapVersion);
(var soap, var soapNamespace, var qualifiedBindingName, var qualifiedPortName) = GetSoapMetaParameters(bindingInfo);


writer.WriteStartElement("wsdl", "port", Namespaces.WSDL_NS);
writer.WriteAttributeString("name", PortName + $"_{soapName}");
writer.WriteAttributeString("binding", "tns:" + BindingName + $"_{soapName}");
writer.WriteAttributeString("name", qualifiedPortName);
writer.WriteAttributeString("binding", "tns:" + qualifiedBindingName);

writer.WriteStartElement(soapName, "address", soapNamespace);
writer.WriteStartElement(soap, "address", soapNamespace);

writer.WriteAttributeString("location", _baseUrl);
writer.WriteEndElement(); // soap:address
Expand Down
Loading

0 comments on commit 6834c3f

Please sign in to comment.