Groups | Blog | Home
all groups > dotnet web services > july 2007 >

dotnet web services : Web References and maxOccurs > 1


Gustaf
7/30/2007 12:45:59 PM
In the thread "Library differences when adding Web Reference" I reported a case where a client app couldn't access all the classes exposed by a Web Service. I've returned to this problem again, and found that it's a 'maxOccurs' attribute in the schema that causes it. Here's an example schema:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns="http://example.org/Foo"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.org/Foo"
elementFormDefault="qualified">

<xs:complexType name="BookType">
<xs:sequence>
<xs:element name="Title" type="xs:string"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="BookListType">
<xs:sequence>
<xs:element name="Book" type="BookType" maxOccurs="2"/>
</xs:sequence>
</xs:complexType>

<xs:element name="BookList" type="BookListType"/>

</xs:schema>

If maxOccurs > 1 on the Book element, it causes the BookListType.Book property to be an array:

public BookType[] Book { set; get; }

This appears to be correct, so there's no problem with the code generated by xsd.exe. I import the generated classes, and replace the HelloWorld() method with this in Service.asmx:

[WebMethod]
public BookListType GetBookList()
{
return null;
}

Now I got a Web Service, which the following public members:

public class Service : System.Web.Services.WebService
public BookListType GetBookList()
public Service()

public class BookListType
public BookType[] Book { set; get; }

public class BookType
public string Title { set; get; }

Next step is to use the Web Service from a client app. But when I add a Web Reference to this Web Service, the BookListType class *disappears*. If I set maxOccurs to '1' in the schema, regenerate the proxy, build and update the reference, it doesn't disappear. So the "Add Web Reference..." wizard in .NET doesn't support Web Services with array parameters. I guess it's a bug in the wizard. Can you add the reference manually, without the wizard, and thereby get access to the BookListType class? Or do I need to use another platform than .NET to test my Web Service?

John Saunders [MVP]
7/30/2007 1:57:25 PM
[quoted text, click to view]

Gustaf, try using maxOccurs="unbounded", just to see if that works.

Also, please remind us which version of .NET you're using.
--
John Saunders [MVP]
Gustaf
7/31/2007 12:00:00 AM
[quoted text, click to view]

Unbounded also creates an array, as expected. The .NET version is 2.0.

John Saunders [MVP]
7/31/2007 1:17:45 PM
[quoted text, click to view]

Yes, but I thought the issue was that "2" prevented the element from
appearing in the client proxy. My question was, with "unbounded", does it
appear in the proxy?
--
John Saunders [MVP]
John Saunders [MVP]
7/31/2007 7:55:04 PM
[quoted text, click to view]

This doesn't make any sense. You're saying that if you use
maxOccurs="unbounded", that it ignores the BookTypeList class because it
contains a property that returns an array? If you can confirm this, and
re-confirm which .NET versions you're using, I'll try to reproduce it ASAP.

I've got arrays in MY web services, and _really_ hope you're wrong!
--
John Saunders [MVP]
Gustaf
8/1/2007 12:36:49 AM
[quoted text, click to view]

The element/class always appear in the generated proxy code. The
generated code is fine, so this is not a problem with xsd.exe. No matter
if maxOccurs is "2" or "unbounded", the element becomes an object array,
as expected:

public BookType[] Book { set; get; }

The problem is on the client side, with the "Add Web Reference..."
wizard. It ignores the BookTypeList class because it contains a property
that returns an array. And it doesn't matter if the array is the return
value, or if it's a parameter, as in

[WebMethod]
public void SetBookList(BookListType list)
{

}

It just seem like the wizard doesn't support object arrays or arrays in
general. The Web Service is probably working already, but I've no way of
knowing, because I can't build a client!

Gustaf
8/1/2007 2:31:59 PM
[quoted text, click to view]

Yes, you got it right. I'm using Visual Studio 2005. I'm not aware of a way to change the .NET version, so I suppose it's 2.0. The Help > About dialog says:

Microsoft Visual Studio 2005
Version 8.0.50727.762 (SP.050727-7600)
Microsoft .NET Framework
Version 2.0.50727

To reproduce the bug, follow these steps:

1. Generate a proxy class from the BookList schema:

xsd /c booklist.xsd

2. In the generated code, see that you got a Book property containing an array of BookType objects.

public BookType[] Book { ... }

This is because maxOccurs > 1 or "unbounded" on the Book element.

3. Create a new Web Service project and add the generated code to the App_Code folder.

4. In Service.cs, replace HelloWorld() with any method that either takes or returns a BookListType object.

[WebMethod]
public BookListType GetBookList()
{
return null;
}

Note that you got access to the BookListType object in the Web Service project.

5. Add a console project to the same solution. This will be the client.

6. Add a Web Reference to the Web Service, and check which classes are made available in Object Browser. The BookListType class will be done, because it contains a property with an array return value/parameter.

Gustaf
Gustaf
8/1/2007 2:38:36 PM
[quoted text, click to view]

Of course I mean "The BookListType class will be *gone* [...]" :-)

John Saunders [MVP]
8/11/2007 7:41:42 PM
[quoted text, click to view]

Gustaf, sorry I haven't gotten back to you. A sudden change in requirements
has kept me from it. I've still got this topic flagged for action, and will
get to it ASAP.

"ASAP" changed it's meaning since I posted it, unfortunately!
--
John Saunders [MVP]
AddThis Social Bookmark Button