By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,143 Members | 865 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,143 IT Pros & Developers. It's quick & easy.

Problem returning container class with DataSet as object

P: n/a
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.Wr iteTypedPrimitive(String
name, String ns, Object o, Boolean xsiType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationWriter1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationWriter1.Write2_ServiceResponse(String
n, String ns, ServiceResponse o, Boolean isNullable, Boolean needType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationWriter1.Write4_ServiceResponse(Object o)
at
Microsoft.Xml.Serialization.GeneratedAssembly.Serv iceResponseSerializer1.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
at System.Xml.Serialization.XmlSerializer.Serialize(X mlWriter xmlWriter,
Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Serialize(X mlWriter xmlWriter,
Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Xml.Serialization.XmlSerializer.Serialize(T extWriter
textWriter, Object o)
at System.Web.Services.Protocols.XmlReturnWriter.Writ e(HttpResponse
response, Stream outputStream, Object returnValue)
at System.Web.Services.Protocols.HttpServerProtocol.W riteReturns(Object[]
returnValues, Stream outputStream)
at System.Web.Services.Protocols.WebServiceHandler.Wr iteReturns(Object[]
returnValues)
at System.Web.Services.Protocols.WebServiceHandler.In voke()

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!
Dec 23 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
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.Wr iteTypedPrimitive(String
name, String ns, Object o, Boolean xsiType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationWriter1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationWriter1.Write2_ServiceResponse(String
n, String ns, ServiceResponse o, Boolean isNullable, Boolean needType)
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationWriter1.Write4_ServiceResponse(Object o)
at
Microsoft.Xml.Serialization.GeneratedAssembly.Serv iceResponseSerializer1.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
at System.Xml.Serialization.XmlSerializer.Serialize(X mlWriter xmlWriter,
Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Serialize(X mlWriter xmlWriter,
Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Xml.Serialization.XmlSerializer.Serialize(T extWriter
textWriter, Object o)
at System.Web.Services.Protocols.XmlReturnWriter.Writ e(HttpResponse
response, Stream outputStream, Object returnValue)
at System.Web.Services.Protocols.HttpServerProtocol.W riteReturns(Object[]
returnValues, Stream outputStream)
at System.Web.Services.Protocols.WebServiceHandler.Wr iteReturns(Object[]
returnValues)
at System.Web.Services.Protocols.WebServiceHandler.In voke()

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!

Dec 27 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.