RE: Problem returning container class with DataSet as object

Tech-Archive recommends: Speed Up your PC by fixing your registry



I did come up with a slight solution however, it is a 'hack' on the dataset
object. If anyone has any thoughts on a complete solution that may include
other classes, Im still open to suggestions.

Basically, since the dataset is just being returned as XML and strings to
work, I simply return an XML formatted string instead of a dataset. Such as...

DataSet ds = db.ExecuteDataSet(cmd);
MemoryStream stream = new MemoryStream();
ds.WriteXml(stream, XmlWriteMode.WriteSchema);
StreamReader reader = new StreamReader(stream);
stream.Position = 0;
resp.ReturnValue = reader.ReadToEnd();

The reason I use this more 'complex' code over ds.WriteXmlSchema is that on
the receiving end I still just want to use the simple ds.ReadXml which
expects XML formatted with ds.WriteXml.


"J. Askey" wrote:

> I am implementing a web service and thought it may be a good idea to return a
> more complex class (which I have called 'ServiceResponse') in order to wrap
> the original return value along with two other properties...
>
> bool error;
> string lastError;
>
> My whole class looks like this...
>
> using System;
> using System.Collections.Generic;
> using System.Text;
> using System.Runtime.Serialization;
>
> namespace My.WebServices
> {
> [Serializable]
> public class ServiceResponse
> {
> public bool error = false;
> public string lastError = "";
> public object returnObject = null;
>
> public ServiceResponse()
> {
>
> }
> }
> }
>
> A sample method on my WebService looks like...
>
> [WebMethod]
> public ServiceResponse Ping(string deviceId)
> {
> ServiceResponse resp = new ServiceResponse();
> if (IsValidDevice(deviceId))
> {
> resp.ReturnValue = true;
> }
> else
> {
> resp.Error = true;
> resp.LastError = DEVICE_UNKNOWN_ERROR;
> resp.ReturnValue = false;
> }
> return resp;
> }
>
> and a client side call looks like...
>
> My.WebServices.Service svc = new My.WebServices.Service();
> My.WebServices.ServiceResponse resp;
> resp = (My.WebServices.ServiceResponse)svc.Ping(deviceId);
> if (!resp.Error)
> {
> //do something
> }
>
> So, this works lovely... and solves my needs. However, if I have a web
> service method that returns a DataSet as an object in the ServiceResponse...
> such as...
>
> [WebMethod]
> public ServiceResponse GetUsers(string deviceId)
> {
> ServiceResponse resp = new ServiceResponse();
> if (IsValidDevice(deviceId))
> {
> try
> {
> string sql = "select * from [user] where enabled = 1";
> SqlCommand cmd = new SqlCommand(sql);
> SqlDatabase db = new SqlDatabase(CONNECTION_STRING);
> DataSet ds = db.ExecuteDataSet(cmd);
> resp.ReturnValue = ds;
> }
> catch (Exception ex)
> {
> resp.Error = true;
> resp.LastError = ex.Message;
> }
> }
> else
> {
> resp.Error = true;
> resp.LastError = DEVICE_UNKNOWN_ERROR;
> }
> return resp;
> }
>
> I get an error calling this method...
>
> System.InvalidOperationException: There was an error generating the XML
> document. ---> System.InvalidOperationException: The type System.Data.DataSet
> may not be used in this context. To use System.Data.DataSet as a parameter,
> return type, or member of a class or struct, the parameter, return type, or
> member must be declared as type System.Data.DataSet (it cannot be object).
> Objects of type System.Data.DataSet may not be used in un-typed collections,
> such as ArrayLists.
> at
> System.Xml.Serialization.XmlSerializationWriter.WriteTypedPrimitive(String
> name, String ns, Object o, Boolean xsiType)
> at
> Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
> at
> Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write2_ServiceResponse(String
> n, String ns, ServiceResponse o, Boolean isNullable, Boolean needType)
> at
> Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write4_ServiceResponse(Object o)
> at
> Microsoft.Xml.Serialization.GeneratedAssembly.ServiceResponseSerializer1.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
> at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter,
> Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
> --- End of inner exception stack trace ---
> at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter,
> Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
> at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter
> textWriter, Object o)
> at System.Web.Services.Protocols.XmlReturnWriter.Write(HttpResponse
> response, Stream outputStream, Object returnValue)
> at System.Web.Services.Protocols.HttpServerProtocol.WriteReturns(Object[]
> returnValues, Stream outputStream)
> at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[]
> returnValues)
> at System.Web.Services.Protocols.WebServiceHandler.Invoke()
>
> I think I understand that the problem is because my
> ServiceResponse.ReturnValue is of type 'object', SOAP does not know how to
> format a complex type such as a DataSet?
>
> So, at this point, Im sort of at a loss on which direction to head. Here are
> the options that I see I have but Im not clear on which are best or even
> feasible.
>
> 1. Somehome make my ServiceResponse class serialize complex types manually
> by implementing the iSerializable interface?
> 2. Drop this return wrapper and use exceptions on the WebService side to
> throw errors and post messages.
> 3. Some other method that I have not though of??
>
> Thank you for any suggestions... Merry Christmas!
>
>
.



Relevant Pages

  • Problem returning container class with DataSet as object
    ... I am implementing a web service and thought it may be a good idea to return a ... more complex class (which I have called 'ServiceResponse') in order to wrap ... name, String ns, Object o, Boolean xsiType) ... returnValues, Stream outputStream) ...
    (microsoft.public.dotnet.framework.webservices)
  • Re: XmlDocumentClass and Finding Nodes
    ... <ServiceResponse> ... <ManagedEntitites> ... into a string, unreplace the substitutions that were made, and then parse that string ... references whould change that string to ...
    (microsoft.public.dotnet.xml)
  • Consuming web service with complex types
    ... I've built a web service method which takes a few strings and a complex type ... I've added the web reference to my ... public InteriorHealth.Schema.ResultValue UploadDocument(string User, string ... DocumentSource, PatientIdentifier Patient) ...
    (microsoft.public.biztalk.general)
  • xml schema design
    ... Have a StateCode simple type that has to be 2 characters long. ... Street (string) ... Have a Venue complex type that has the following: ... Have an element that can contain only 1 instance of the Venue complex ...
    (microsoft.public.dotnet.xml)
  • Re: xml schema design
    ... Have a StateCode simple type that has to be 2 characters long. ... Street (string) ... Have a Venue complex type that has the following: ... Sounds fine to me, you might additionally restrict zip code to five digits, enumerate the possible state codes. ...
    (microsoft.public.dotnet.xml)