Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / ASP.NET / Web Services / December 2005

Tip: Looking for answers? Try searching our database.

Problem returning container class with DataSet as object

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
J. Askey - 23 Dec 2005 20:26 GMT
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!
J. Askey - 27 Dec 2005 15:24 GMT
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.

> 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
[quoted text clipped - 138 lines]
>
> Thank you for any suggestions... Merry Christmas!

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.