Microsoft KB Archive/317340

= BUG: A Typed DataSet That Imports a Secondary Schema Cannot be Used As a Method Parameter or As a Return Type with ASP.NET Web Services =

Article ID: 317340

Article Last Modified on 11/7/2003

-

APPLIES TO


 * Microsoft Web Services (included with the .NET Framework)

-



This article was previously published under Q317340



SYMPTOMS
You cannot create a Web service proxy when the Typed DataSet that imports a secondary schema is used as a parameter or as a return type from the WebMethod. If you try to do this, the following symptoms may occur:  When you generate the Web service proxy class by using the Web Services Description Language (WSDL) tool, WSDL.exe fails. You receive the following warning message and error message:

Warning: Schema could not be validated. Class generation may fail or may produce incorrect results.

Error generating DataSet for schema 'SchemaNamespace'.

where 'SchemaNamespace' is the namespace of the schema. The Visual Studio .NET Web References wizard does not produce a Web service proxy for your Web service. No errors are reported. However, you find that the References.cs file or the References.vb file (that contains the proxy definition) do not exist. Also, the client application cannot declare instances of the Web service proxy.



CAUSE
When you create the Web service proxy that uses Typed DataSet, the Typed DataSet does not correctly import secondary schemas. Instead of using the expected secondary schema, the returned schema imports a schema with an arbitrary name such as _app1.xsd. Because of an incorrect secondary schema name, the tools such as WSDL.exe or Microsoft Visual Studio .NET cannot correctly create a proxy for the Web service. Also, the returned XML cannot be serialized back to a corresponding Typed DataSet instance. If you try to do this, the result is an XmlSchemaException.



WORKAROUND
To work around this problem, return the Typed DataSet that you want as an XmlElement in your WebMethod. In your client, you can explicitly load the returned XML to an instance of the Typed DataSet that you want. The following code is an example for WebMethod:

Visual Basic .NET  Public Function GetTypedDataSet As System.Xml.XmlElement ' Create an instance of Typed DataSet. Dim myDs As MyTypedDataSet = New MyTypedDataSet

' Populate the DataSet with the Data. Dim myCn As New System.Data.SqlClient.SqlConnection(&quot;Persist Security Info=False;User ID= ;Password= ;Initial Catalog=pubs;Data Source=SQLServer;Packet Size=4096&quot;) myCn.Open Dim myDa As New System.Data.SqlClient.SqlDataAdapter(&quot;Select * from Employee&quot;, myCn) myDa.Fill(myDs, myDs.Tables(1).TableName)

' Return the DataSet as an XmlElement. Dim xdd As System.Xml.XmlDataDocument = New System.Xml.XmlDataDocument(myDs) Dim docElem As System.Xml.XmlElement = xdd.DocumentElement Return docElem End Function Visual C# .NET [WebMethod] public System.Xml.XmlElement GetTypedDataSet {           // Create an instance of Typed DataSet. MyTypedDataSet myDs = new MyTypedDataSet ; // Add some data to the DataSet. System.Data.SqlClient.SqlConnection myCn =new System.Data.SqlClient.SqlConnection(&quot;Persist Security Info=False;User ID= ;Password= ;Initial Catalog=pubs;Data Source=SQLServer;Packet Size=4096&quot;); myCn.Open; System.Data.SqlClient.SqlDataAdapter myDa = new System.Data.SqlClient.SqlDataAdapter(&quot;Select * from Employee&quot;, myCn); myDa.Fill(myDs, myDs.Tables[1].TableName);

// Return the DataSet as an XmlElement. System.Xml.XmlDataDocument xdd = new System.Xml.XmlDataDocument (myDs); System.Xml.XmlElement docElem = xdd.DocumentElement; return docElem ; } Modify the SQL connection string to access data from Microsoft SQL Server.

The following code shows the sample client that calls the WebMethod:

Visual Basic .NET Public Sub GetData

' Create an instance of Typed DataSet. Dim ds As MyTypedDataSet = New MyTypedDataSet

' Create an instance of Web service proxy. Dim WebProxy As MyWebServiceProxy = New MyWebServiceProxy

' Get the data from Webservice Dim elem As XmlElement = WebProxy.GetTypedDataSet

' Load the XML to the Typed DataSet that you want. Dim nodeReader As XmlNodeReader = New XmlNodeReader(elem) ds.ReadXml(nodeReader, XmlReadMode.Auto)

' Use Typed DataSet as you would typically do. End Sub Visual C# .NET public void GetData {   // Create an instance of Typed DataSet. MyTypedDataSet ds = new MyTypedDataSet ;

// Create an instance of Web service proxy. MyWebServiceProxy WebProxy = new MyWebServiceProxy ;

// Get the data from Webservice. XmlElement elem = WebProxy.GetTypedDataSet ;

// Load the XML to the Typed DataSet that you want. XmlNodeReader nodeReader = new XmlNodeReader (elem) ; ds.ReadXml (nodeReader, XmlReadMode.Auto) ;

// Use Typed DataSet as you would typically do. }



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.



Steps to Reproduce the Problem
  Save the following XSD schema file as c:\Employee.xsd :  <xs:schema id=&quot;MyTypedDataSet&quot; targetNamespace=&quot;MyTypedDataSetNamespace&quot; xmlns:mstns=&quot;MyTypedDataSetNamespace&quot; xmlns=&quot;MyMyTypedDataSetDataSetNamespace&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:msdata=&quot;urn:schemas-microsoft-com:xml-msdata&quot; attributeFormDefault=&quot;qualified&quot; elementFormDefault=&quot;qualified&quot;> <xs:element name=&quot;MyTypedDataSet&quot; msdata:IsDataSet=&quot;true&quot;> <xs:complexType> <xs:choice maxOccurs=&quot;unbounded&quot;> <xs:element name=&quot;Employee&quot;> <xs:complexType> <xs:sequence> <xs:element name=&quot;emp_id&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;fname&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;minit&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;lname&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;job_id&quot; type=&quot;xs:short&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;job_lvl&quot; type=&quot;xs:unsignedByte&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;pub_id&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; /> <xs:element name=&quot;hire_date&quot; type=&quot;xs:dateTime&quot; minOccurs=&quot;0&quot; /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> Note This is an XSD schema for the Employee table of the Pubs database of SQL Server. </li>  Save the following file as c:\SecondarySchema.xsd : <?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?> <xs:schema id=&quot;MySecDataSet&quot; targetNamespace=&quot;MySecDataSetNamespace&quot; xmlns:mstns=&quot;MySecDataSetNamespace&quot; xmlns=&quot;MySecDataSetNamespace&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:msdata=&quot;urn:schemas-microsoft-com:xml-msdata&quot; attributeFormDefault=&quot;qualified&quot; elementFormDefault=&quot;qualified&quot;> <xs:element name=&quot;EmployeeCity&quot;> <xs:complexType> <xs:sequence> <xs:element name=&quot;City&quot; type=&quot;xs:string&quot; minOccurs=&quot;0&quot; /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> </li>  To import the SecondarySchema file, add the following code before the MyTypedDataSet element that is in the Employee.xsd file: <xs:import id =&quot;XMLSchema11&quot; namespace = &quot;MySecDataSetNamespace&quot; schemaLocation =&quot;file:///c:\SecondarySchema.xsd&quot; /> </li> Open the Visual Studio .NET command prompt and then change to the folder c:\.</li> At the command prompt, type one of the following commands to create the Typed DataSet class file: <ol style="list-style-type: lower-alpha;"> For Visual Basic .NET, type: xsd.exe /d /l:vb Employee.xsd.

The Employee.vb file is created.</li> For Visual C# .NET, type: xsd.exe /d Employee.xsd.

The Employee.cs file is created.</li></ol> </li> In Visual Studio .NET, create a new ASP.NET Web service project that is named TestTypedDS by using Visual Basic .NET or Visual C# .NET.

By default, Service1.asmx is created.</li> On the Project menu, click Add Existing Item. Move to drive C and then select Employee.vb or Employee.cs.

The file that you select depends on the language that you use in your project.</li>  In Solution Explorer, right-click Service1.asmx and then click View Code. Add the following code to create a WebMethod:

For Visual Basic .NET: <WebMethod> Public Function GetTypedDataSet As MyTypedDataSet Dim myDs As New MyTypedDataSet Dim myCn As New System.Data.SqlClient.SqlConnection(&quot;Persist Security Info=False;User ID= ;Password= ;Initial Catalog=pubs;Data Source=SQLServer;Packet Size=4096&quot;) myCn.Open Dim myDa As New System.Data.SqlClient.SqlDataAdapter(&quot;Select * from Employee&quot;, myCn) myDa.Fill(myDs, myDs.Tables(1).TableName) Return myDs End Function For Visual C# .NET: [WebMethod] public MyTypedDataSet GetTypedDataSet {           MyTypedDataSet myDs = new MyTypedDataSet; System.Data.SqlClient.SqlConnection myCn =new System.Data.SqlClient.SqlConnection(&quot;Persist Security Info=False;User ID= ;Password= ;Initial Catalog=pubs;Data Source=SQLServer;Packet Size=4096&quot;); myCn.Open; System.Data.SqlClient.SqlDataAdapter myDa = new System.Data.SqlClient.SqlDataAdapter(&quot;Select * from Employee&quot;, myCn); myDa.Fill(myDs, myDs.Tables[1].TableName); return myDs; } </li> Modify the SQL connection string to access data from your SQL Server.</li> On the Debug menu, click Start to run the application.</li> Click the TestDataSet link and then click Invoke.</li> Verify that the secondary schema is incorrectly imported as _app1.xsd.</li> Create a new ASP.NET Web Application project by using Visual Basic .NET or Visual C# .NET.</li> In Solution Explorer, right-click References and then click Add Web Reference.</li> In the Address text box, type http://localhost/TestTypedDS/Service1.asmx and then press ENTER.</li> <li>Click Add Reference.</li> <li>In Solution Explorer, right-click WebForm1.aspx and then click View Code.</li> <li>If you try to create an instance of the Web service proxy in the Page_Load event handler, you cannot. You cannot do this because the proxy class has not been generated correctly.

Use the WSDL tool and try to create a Web service proxy class: <ol style="list-style-type: lower-alpha;"> <li>At the Visual Studio .NET command prompt, type the following command: wsdl.exe &quot;http://localhost/TestTypedDS/Service1.asmx?wsdl&quot; .</li> <li>Press ENTER.</li> <li>The error message in the Symptoms section appears.</li></ol> </li></ol>

<div class="references_section">