Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.0.23 #786

Merged
merged 31 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6fdc700
fix issue when object was serialized twice if using rpc format
Dec 1, 2021
953dd3b
configured XmlReader to use IgnoreWhitespace = true
andersjonsson Dec 1, 2021
f3811b6
Merge pull request #768 from dmolochnikov/fix-duplicate-object-serial…
kotovaleksandr Dec 2, 2021
096c5c2
Merge pull request #769 from andersjonsson/ignore-insignificant-white…
kotovaleksandr Dec 2, 2021
8c367b5
added failing test with call that works on .net48 web service
andersjonsson Dec 2, 2021
cdb6174
malformed xml
andersjonsson Dec 2, 2021
8556cc0
added special case for arrayOfInt and a test for both variants
andersjonsson Dec 2, 2021
0f6dd0c
Added handling for all primitive types except float, double, IntPtr a…
andersjonsson Dec 2, 2021
ccbd058
set dtdprocessing to prohibit to get rid of code analysis warning
andersjonsson Dec 3, 2021
44b3b75
nit: fixed malformed if-statement
andersjonsson Dec 3, 2021
9985108
Merge pull request #772 from andersjonsson/set-dtdprocessing-prohibit
kotovaleksandr Dec 3, 2021
75abbf4
Merge branch 'develop' into array-of-primitives-without-wrapping
andersjonsson Dec 3, 2021
3f842e7
Treat invalid array input as empty array and skip any value in the xm…
andersjonsson Dec 3, 2021
5a57e10
removed unused member
andersjonsson Dec 3, 2021
b0aec1e
cleanup of double test
andersjonsson Dec 3, 2021
706823b
Merge pull request #771 from andersjonsson/array-of-primitives-withou…
kotovaleksandr Dec 3, 2021
94dfa25
fix issue #575 (https://github.com/DigDes/SoapCore/issues/575) reques…
Dec 8, 2021
7bb8a33
support for extra xmlnamespaceprefixoverrides per messageversion
andersjonsson Dec 16, 2021
16f5f24
remove style from wsdl binding
andersjonsson Dec 16, 2021
d8d9037
fix code style
Dec 17, 2021
e610905
added ability to set custom bindingname and portname per SoapMessageE…
andersjonsson Dec 17, 2021
f8842f1
moved the new xmlNamespaceOverrides to SoapMessageEncoder, to get rid…
andersjonsson Dec 17, 2021
18226e3
missed one instance of the override dictionary
andersjonsson Dec 17, 2021
2a7b687
Merge pull request #785 from andersjonsson/specify-binding-and-portna…
kotovaleksandr Dec 20, 2021
ebba165
Merge pull request #784 from andersjonsson/remove-style-from-wsdl-bin…
kotovaleksandr Dec 20, 2021
a860c62
fixed conflicts with develop
andersjonsson Dec 20, 2021
e4b5475
fixed failing test
andersjonsson Dec 20, 2021
c1b4b3d
add unit test to prove fix is working
Dec 20, 2021
c2c461d
Merge pull request #782 from andersjonsson/namespace-overrides-per-me…
kotovaleksandr Dec 20, 2021
323e2f8
Merge pull request #777 from dmolochnikov/fix-message-contract-parame…
kotovaleksandr Dec 20, 2021
cbf7428
v1.1.0.23
kotovaleksandr Dec 20, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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