diff --git a/src/SoapCore/Meta/MetaBodyWriter.cs b/src/SoapCore/Meta/MetaBodyWriter.cs index e1940b84..a6ff50d8 100644 --- a/src/SoapCore/Meta/MetaBodyWriter.cs +++ b/src/SoapCore/Meta/MetaBodyWriter.cs @@ -220,9 +220,9 @@ private void WriteParameters(XmlDictionaryWriter writer, SoapMethodParameterInfo var typeRootName = string.IsNullOrWhiteSpace(xmlRootAttr?.ElementName) ? null : xmlRootAttr.ElementName; var parameterName = elementName - ?? parameterInfo.Parameter.GetCustomAttribute()?.Name - ?? typeRootName - ?? parameterInfo.Parameter.Name; + ?? parameterInfo.Parameter.GetCustomAttribute()?.Name + ?? typeRootName + ?? parameterInfo.Parameter.Name; AddSchemaType(writer, parameterInfo.Parameter.ParameterType, parameterName, @namespace: elementAttribute?.Namespace); } @@ -495,13 +495,16 @@ private void AddMessage(XmlDictionaryWriter writer) } // output - writer.WriteStartElement("wsdl", "message", Namespaces.WSDL_NS); - writer.WriteAttributeString("name", $"{BindingType}_{operation.Name}_OutputMessage"); - writer.WriteStartElement("wsdl", "part", Namespaces.WSDL_NS); - writer.WriteAttributeString("name", "parameters"); - writer.WriteAttributeString("element", "tns:" + responseTypeName); - writer.WriteEndElement(); // wsdl:part - writer.WriteEndElement(); // wsdl:message + if (!operation.IsOneWay) + { + writer.WriteStartElement("wsdl", "message", Namespaces.WSDL_NS); + writer.WriteAttributeString("name", $"{BindingType}_{operation.Name}_OutputMessage"); + writer.WriteStartElement("wsdl", "part", Namespaces.WSDL_NS); + writer.WriteAttributeString("name", "parameters"); + writer.WriteAttributeString("element", "tns:" + responseTypeName); + writer.WriteEndElement(); // wsdl:part + writer.WriteEndElement(); // wsdl:message + } } } @@ -516,9 +519,12 @@ private void AddPortType(XmlDictionaryWriter writer) writer.WriteStartElement("wsdl", "input", Namespaces.WSDL_NS); writer.WriteAttributeString("message", $"tns:{BindingType}_{operation.Name}_InputMessage"); writer.WriteEndElement(); // wsdl:input - writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); - writer.WriteAttributeString("message", $"tns:{BindingType}_{operation.Name}_OutputMessage"); - writer.WriteEndElement(); // wsdl:output + if (!operation.IsOneWay) + { + writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); + writer.WriteAttributeString("message", $"tns:{BindingType}_{operation.Name}_OutputMessage"); + writer.WriteEndElement(); // wsdl:output + } writer.WriteEndElement(); // wsdl:operation } @@ -553,11 +559,14 @@ private void AddBinding(XmlDictionaryWriter writer) writer.WriteEndElement(); // soap:body writer.WriteEndElement(); // wsdl:input - writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); - writer.WriteStartElement(soap, "body", soapNamespace); - writer.WriteAttributeString("use", "literal"); - writer.WriteEndElement(); // soap:body - writer.WriteEndElement(); // wsdl:output + if (!operation.IsOneWay) + { + writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); + writer.WriteStartElement(soap, "body", soapNamespace); + writer.WriteAttributeString("use", "literal"); + writer.WriteEndElement(); // soap:body + writer.WriteEndElement(); // wsdl:output + } writer.WriteEndElement(); // wsdl:operation } diff --git a/src/SoapCore/Meta/MetaWCFBodyWriter.cs b/src/SoapCore/Meta/MetaWCFBodyWriter.cs index b8e832f4..c04019f7 100644 --- a/src/SoapCore/Meta/MetaWCFBodyWriter.cs +++ b/src/SoapCore/Meta/MetaWCFBodyWriter.cs @@ -172,7 +172,8 @@ private void WriteParameters(XmlDictionaryWriter writer, SoapMethodParameterInfo var parameterName = !string.IsNullOrEmpty(elementAttribute?.ElementName) ? elementAttribute.ElementName : parameterInfo.Parameter.GetCustomAttribute()?.Name ?? parameterInfo.Parameter.Name; - AddSchemaType(writer, parameterInfo.Parameter.ParameterType, parameterName, objectNamespace: elementAttribute?.Namespace ?? (parameterInfo.Namespace != "http://tempuri.org/" ? parameterInfo.Namespace : null)); + var isRequired = !parameterInfo.Parameter.IsOptional; + AddSchemaType(writer, parameterInfo.Parameter.ParameterType, parameterName, objectNamespace: elementAttribute?.Namespace ?? (parameterInfo.Namespace != "http://tempuri.org/" ? parameterInfo.Namespace : null), isRequired: isRequired); } } @@ -270,7 +271,8 @@ private void AddOperations(XmlDictionaryWriter writer) } var returnName = operation.DispatchMethod.ReturnParameter.GetCustomAttribute()?.Name ?? operation.Name + "Result"; - AddSchemaType(writer, returnType, returnName, false, GetDataContractNamespace(returnType)); + var isRequired = !operation.DispatchMethod.ReturnParameter.IsOptional; + AddSchemaType(writer, returnType, returnName, false, GetDataContractNamespace(returnType), isRequired: isRequired); } WriteParameters(writer, operation.OutParameters); @@ -796,6 +798,7 @@ private void WriteComplexType(XmlDictionaryWriter writer, Type type) var attributes = property.GetCustomAttributes(true); int order = 0; + bool isRequired = false; foreach (var attr in attributes) { if (attr is DataMemberAttribute dataContractAttribute) @@ -810,6 +813,8 @@ private void WriteComplexType(XmlDictionaryWriter writer, Type type) order = dataContractAttribute.Order; } + isRequired = dataContractAttribute.IsRequired; + break; } } @@ -818,13 +823,14 @@ private void WriteComplexType(XmlDictionaryWriter writer, Type type) { Name = propertyName, Type = property.PropertyType, - Order = order + Order = order, + IsRequired = isRequired }); } foreach (var p in dataMembersToWrite.OrderBy(x => x.Order).ThenBy(p => p.Name, StringComparer.Ordinal)) { - AddSchemaType(writer, p.Type, p.Name, false, GetDataContractNamespace(p.Type)); + AddSchemaType(writer, p.Type, p.Name, false, GetDataContractNamespace(p.Type), p.IsRequired); } } @@ -855,13 +861,16 @@ private void AddMessage(XmlDictionaryWriter writer) writer.WriteEndElement(); // wsdl:message // output - writer.WriteStartElement("wsdl", "message", Namespaces.WSDL_NS); - writer.WriteAttributeString("name", $"{BindingType}_{operation.Name}_OutputMessage"); - writer.WriteStartElement("wsdl", "part", Namespaces.WSDL_NS); - writer.WriteAttributeString("name", "parameters"); - writer.WriteAttributeString("element", "tns:" + operation.Name + "Response"); - writer.WriteEndElement(); // wsdl:part - writer.WriteEndElement(); // wsdl:message + if (!operation.IsOneWay) + { + writer.WriteStartElement("wsdl", "message", Namespaces.WSDL_NS); + writer.WriteAttributeString("name", $"{BindingType}_{operation.Name}_OutputMessage"); + writer.WriteStartElement("wsdl", "part", Namespaces.WSDL_NS); + writer.WriteAttributeString("name", "parameters"); + writer.WriteAttributeString("element", "tns:" + operation.Name + "Response"); + writer.WriteEndElement(); // wsdl:part + writer.WriteEndElement(); // wsdl:message + } AddMessageFaults(writer, operation); } @@ -895,10 +904,14 @@ private void AddPortType(XmlDictionaryWriter writer) writer.WriteAttributeString("wsam", "Action", Namespaces.WSAM_NS, operation.SoapAction); writer.WriteAttributeString("message", $"tns:{BindingType}_{operation.Name}_InputMessage"); writer.WriteEndElement(); // wsdl:input - writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); - writer.WriteAttributeString("wsam", "Action", Namespaces.WSAM_NS, operation.SoapAction + "Response"); - writer.WriteAttributeString("message", $"tns:{BindingType}_{operation.Name}_OutputMessage"); - writer.WriteEndElement(); // wsdl:output + + if (!operation.IsOneWay) + { + writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); + writer.WriteAttributeString("wsam", "Action", Namespaces.WSAM_NS, operation.SoapAction + "Response"); + writer.WriteAttributeString("message", $"tns:{BindingType}_{operation.Name}_OutputMessage"); + writer.WriteEndElement(); // wsdl:output + } AddPortTypeFaults(writer, operation); @@ -953,11 +966,14 @@ private void AddBinding(XmlDictionaryWriter writer) writer.WriteEndElement(); // soap:body writer.WriteEndElement(); // wsdl:input - writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); - writer.WriteStartElement("soap", "body", Namespaces.SOAP11_NS); - writer.WriteAttributeString("use", "literal"); - writer.WriteEndElement(); // soap:body - writer.WriteEndElement(); // wsdl:output + if (!operation.IsOneWay) + { + writer.WriteStartElement("wsdl", "output", Namespaces.WSDL_NS); + writer.WriteStartElement("soap", "body", Namespaces.SOAP11_NS); + writer.WriteAttributeString("use", "literal"); + writer.WriteEndElement(); // soap:body + writer.WriteEndElement(); // wsdl:output + } AddBindingFaults(writer, operation); @@ -1000,7 +1016,7 @@ private void AddService(XmlDictionaryWriter writer) writer.WriteEndElement(); // wsdl:port } - private void AddSchemaType(XmlDictionaryWriter writer, Type type, string name, bool isArray = false, string objectNamespace = null) + private void AddSchemaType(XmlDictionaryWriter writer, Type type, string name, bool isArray = false, string objectNamespace = null, bool isRequired = false) { var typeInfo = type.GetTypeInfo(); var typeName = GetTypeName(type); @@ -1035,7 +1051,7 @@ private void AddSchemaType(XmlDictionaryWriter writer, Type type, string name, b if (isArray) { - writer.WriteAttributeString("minOccurs", "0"); + writer.WriteAttributeString("minOccurs", isRequired ? "1" : "0"); writer.WriteAttributeString("maxOccurs", "unbounded"); } } @@ -1075,7 +1091,7 @@ private void AddSchemaType(XmlDictionaryWriter writer, Type type, string name, b } } - writer.WriteAttributeString("minOccurs", "0"); + writer.WriteAttributeString("minOccurs", isRequired ? "1" : "0"); if (isArray) { writer.WriteAttributeString("maxOccurs", "unbounded"); @@ -1091,7 +1107,7 @@ private void AddSchemaType(XmlDictionaryWriter writer, Type type, string name, b } else { - writer.WriteAttributeString("minOccurs", "0"); + writer.WriteAttributeString("minOccurs", isRequired ? "1" : "0"); if (isArray) { writer.WriteAttributeString("maxOccurs", "unbounded"); diff --git a/src/SoapCore/ServiceModel/DataMemberDescription.cs b/src/SoapCore/ServiceModel/DataMemberDescription.cs index a0814af6..27407612 100644 --- a/src/SoapCore/ServiceModel/DataMemberDescription.cs +++ b/src/SoapCore/ServiceModel/DataMemberDescription.cs @@ -7,5 +7,6 @@ public class DataMemberDescription public Type Type { get; set; } public string Name { get; set; } public int? Order { get; set; } + public bool IsRequired { get; set; } } } diff --git a/src/SoapCore/SoapCore.csproj b/src/SoapCore/SoapCore.csproj index 9a00f43b..bd678ff4 100644 --- a/src/SoapCore/SoapCore.csproj +++ b/src/SoapCore/SoapCore.csproj @@ -2,7 +2,7 @@ SOAP protocol middleware for ASP.NET Core - 1.1.0.1-alpha + 1.1.0.1-beta Digital Design netcoreapp3.0;netstandard2.0;netcoreapp2.1;netcoreapp3.1 SoapCore @@ -14,7 +14,7 @@ false false false - 1.1.0.1-alpha + 1.1.0.1-beta false SoapCore.snk true