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! 1 5421
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!
This discussion thread is closed Replies have been disabled for this discussion. Similar topics
9 posts
views
Thread by Morten |
last post: by
|
reply
views
Thread by Albert |
last post: by
|
2 posts
views
Thread by Stephen Miller |
last post: by
|
8 posts
views
Thread by I am Sam |
last post: by
|
4 posts
views
Thread by Girish |
last post: by
|
7 posts
views
Thread by Girish |
last post: by
|
1 post
views
Thread by Miguel Dias Moura |
last post: by
|
4 posts
views
Thread by Brad Baker |
last post: by
| | | | | | | | | | | |