0

A method in my WebService returns a DataSet containing 5 variables. 2 of them are string, 1 int and the 2 others boolean.

After publishing the WebService, that specific response in the wsdl looks like: <s:element minOccurs="0" maxOccurs="1" name="myMethodResult">

Now, people consuming the WebService ask me if I can change it somehow so the wsdl ends up looking something like this:

<s:element minOccurs="1" maxOccurs="1" name="variable1" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="variable2" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="variable3" type="s:int" />
<s:element minOccurs="0" maxOccurs="1" name="variable4" type="s:boolean" />
<s:element minOccurs="1" maxOccurs="1" name="variable5" type="s:boolean" />

How can I achieve that?

Daniel Sh.
  • 2,078
  • 5
  • 42
  • 67

1 Answers1

0

If this is a WCF web service, you can create an attribute that implements IContractBehavior and IWsdlExportExtension as described in this post.

Here is the excerpt of it:

void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
    foreach (var operation in context.Contract.Operations)
    {
        var inputMessage = operation.Messages.
            Where(m => m.Direction == MessageDirection.Input).First();
        var parameters = operation.SyncMethod.GetParameters();

        for (int i = 0; i < parameters.Length; i++)
        {
            object[] attributes = parameters[i].GetCustomAttributes(
                typeof(OptionalAttribute), false);

            if (attributes.Length == 0)
            {
                // The parameter has no [Optional] attribute, add it
                // to the list of parameters that we need to adjust
                // the XML schema for later on.
                _requiredParameter.Add(new RequiredMessagePart()
                    {
                        Namespace = inputMessage.Body.Parts[i].Namespace,
                        Message = operation.Name,
                        Name = inputMessage.Body.Parts[i].Name
                    });
            }
        }
    }
}

void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
{
    foreach (var p in _requiredParameter)
    {
        var schemas = exporter.GeneratedXmlSchemas.Schemas(p.Namespace);

        foreach (XmlSchema schema in schemas)
        {
            var message = (XmlSchemaElement)schema.Elements[p.XmlQualifiedName];
            var complexType = (XmlSchemaComplexType)message.ElementSchemaType;
            var sequence = (XmlSchemaSequence)complexType.Particle;

            foreach (XmlSchemaElement item in sequence.Items)
            {
                if (item.Name == p.Name)
                {
                    item.MinOccurs = 1;
                    item.MinOccursString = "1";
                }
            }
        }
    }
}

with thanks to the author Marcel Veldhuizen.

Jony Adamit
  • 3,178
  • 35
  • 44
  • Sorry for not being that accurate with the info provided. Not a WCF WS but an regular SOAP one. – Daniel Sh. Dec 30 '15 at 14:27
  • 1
    Not that simple then. Check out [this](http://stackoverflow.com/questions/3961112/how-to-make-a-dotnet-webservice-set-minoccurs-1-on-a-string-value) SO answer. You can always change it manually or write some code that updates the text yourself.. – Jony Adamit Dec 30 '15 at 15:05