Control WSDL types section

Skip to first unread message

Armando Garcia

Aug 27, 2002, 4:09:55 PM8/27/02
How can I specify the the minoccur/maxoccur of elements at
the schema generated at the WSDL?

Say, if I have a simple field:
Public aString As String

it is being shown on WSDL as:
<s:element minOccurs="0" maxOccurs="1"
name="aString" type="s:string" />

but what if want to make this element mandatory

The same thing happens for arrays, say:
Public someStrings() As String

in the WSDL it will become a complex type but in the
definition it will show an unbounded at the maxOccurs.

I guess that the idea of having the types section at WSDL
is to fully specify what the service provider expects from
its clients. Now, how do I make sure that the WSDL tells
what do I need?

Adrian Turtschi

Sep 1, 2002, 2:58:19 PM9/1/02
First, you should probably ask yourself:
(i) do I really need to fiddle with the minOccurs/maxOccurs attribute?
(ii) why don't I just use a static WSDL file for my Web service (with the
"massaged" attributes)

However, if you still want to dynamically create WSDL files (using the
http://localhost/vDir/myService.asmx?WSDL) with your own minOccurs values,
here's how to do it:
(A) Create a new System.Attribute that allows you to specify in your Web
method for which in-parameters you want to change the minOccurs attribute in
the WSDL types section.
(B) Create a new SoapExtensionReflector that will change the WSDL generated
by ASP.NET. You need to override one method: ReflectMethod(). You can get at
the WSDL Types information by using
ReflectionContext.ServiceDescription.Types. Massage your type, and write
your changes back.
(C) Register your SoapExtensionReflector in web.config

Here's a concrete example:

(C) web.config: add

<add type="wsdlModify1.customSoapExtensionReflector, wsdlModify1" />

(A) and (B): I have a sample Web service, wsdlModifiy1.Service1, with one
Web method, wsdlModify1.testMethod(...). This method has three arguments,
myArg1 through myArg3. I define an Attribute changeMinOccurs to change the
minOccurs value for a particular in-parameter. In my example, I use this
attribute twice because I want to change the first two in-parameters. All
the actual work is being done in the SoapExtensionReflector

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.Xml;
using System.Xml.Schema;
// public webService wsdlModify1.service1
/// <summary>
/// The public wsdlModify1.service1 Web service demonstrates using
/// SoapExtensionReflector to change the WSDL <types> section
/// </summary>
/// <remarks>
/// <author dev="Adrian Turtschi"></author>
/// <design></design>
/// <history date="09/01/2002" dev="Adrian Turtschi">
/// <delta desc="created Web service"></delta>
/// </history>
/// </remarks>
namespace wsdlModify1 {
public class service1 : System.Web.Services.WebService {

public service1() {

#region Component Designer generated code
private IContainer components = null;
private void InitializeComponent() {
protected override void Dispose( bool disposing ) {
if(disposing && components != null) {

[WebMethod,changeMinOccurs("myArg1", 1), changeMinOccurs("myArg2", 1)]
public string testMethod(string myArg1, string myArg2, string myArg3) {
return myArg1 + myArg2 + myArg3;

public class changeMinOccursAttribute : Attribute {

public changeMinOccursAttribute(string parameter, int minOccurs) {
this.parameter = parameter;
this.minOccurs = minOccurs;

public string parameter;
public int minOccurs;

public class customSoapExtensionReflector : SoapExtensionReflector {
public override void ReflectMethod() {
// get method attributes
changeMinOccursAttribute[] customAttributes =
if (customAttributes != null) {
string defaultNamespace = this.ReflectionContext.DefaultNamespace;
// get the schema in the WSDL <types> section
XmlSchema xmlSchema =
// instead of working directly with the XmlSchema object we load
// the corresponding XML representation of the XSD into an
// XmlDocument and work on that level
MemoryStream memoryStream1 = new MemoryStream();
XmlWriter xmlWriter1 = new XmlTextWriter(memoryStream1,

XmlDocument xmlDocument = new XmlDocument();
memoryStream1.Position = 0;

// now we have an XmlDocument representation of the XSD. Find the
// corresponding elements of those in-parameters for which we want
// change the minOccurs attribute
string xmlSchemaNamespace = "";
XmlNamespaceManager xmlNamespaceManager =
new XmlNamespaceManager(xmlDocument.NameTable);
xmlNamespaceManager.AddNamespace("s", xmlSchemaNamespace);

// loop over all in-parameters of the Web method for which we want
// change the minOccurs attribute
for(int i = 0; i < customAttributes.Length; i++) {
string parameter = customAttributes[i].parameter;
int minOccurs = customAttributes[i].minOccurs;
string xPath = "//s:element[@name='" + parameter + "']";
// get the XSL element
XmlNodeList myNodeList = xmlDocument.DocumentElement.SelectNodes
(xPath, xmlNamespaceManager);
// sanity checks
if((myNodeList.Count == 1) &&
(myNodeList[0].Attributes["minOccurs"] != null)) {
// finally: change minOccurs!
myNodeList[0].Attributes["minOccurs"].Value =

// write the changes back to the WSDL <types> section
MemoryStream memoryStream2 = new MemoryStream();
XmlWriter xmlWriter2 = new XmlTextWriter(memoryStream2,
memoryStream2.Position = 0;
xmlSchema = XmlSchema.Read(memoryStream2, null);

// remove the original version of the WSDL <types> section
// replace with our new version



Adrian Turtschi
Avanade Deutschland GmbH

"Armando Garcia" <> wrote in message

Reply all
Reply to author
0 new messages