.Net Web Services and passing objects (and Data)
I’ve been using Web Services for many years prior to .Net, but with .Net I continue to have some serious mind blocks in terms of how to best pass data between the client and server, specifically when passing data in the form of objects/entities.
The problem I have is that in my business scenarios I usually have business objects both on the client and on the server. I download data from the server, then stick it into client side objects that often times are identical to the server side objects. The problem is .Net does not make this sort of thing easy with its proxy based approach.
The problem is that .Net creates proxy copies of my business objects. These objects are only container shells of the full objects. They get created even if there is nothing omitted from the original object as is the case in a typical entity object. Instead I end up with a weak shell of an object that servers for nothing more than transport.
Once the data arrives on the other end I can’t use the data as is. I have to now move this data into my real business objects that actually do the work on the data. Note that this is true even if I create pure data container classes that don’t include methods.
I keep asking this question and I keep getting blank stares from people – am I really out of my mind here? This seems like a very common scenario. Most people then continue to tell me to pass DataSets across the wire, which works a little better, but even there similar issues exist. If I pass a dataset to the client app I still have to go through all sorts of rigamorole to reattach the data I downloaded to my real life business objects by merging or otherwise kludging the data logic to force the DataSet into the right state on the client.
I’m writing about this because I’m curious for some input. Is everybody really using mostly DataSets to pass data over the wire instead of objects? I mean this completely goes counter the whole OO paradigm of dealing with data in the first place. The Proxy approach works well in true disconnected to the server scenarios, but it's not a good match for side by side applications which in my work tends to be the more common case. Side by side meaning two separate sets of data on the client and server with data being shared between the two as opposed to a central database that is always updated on the server.
What I would like to see at the least is an easier mechanism to map types for the proxies generated. I know I can do this by writing custom code, but it would be nice if we could specify the classes that are used for proxies conditionally.
Another area that would be useful would be tools to facilitate object copying. I’ve built my own routines to do this and true it isn’t rocket science, but this happens frequently enough that it sure would be nice to have a generic way to clone a serializable object easily. So when I get back my AuthorProxyEntity I can then assign it easily to my live Authors.AuthorEntity instance.
I do this now with a cheesy Reflection based CopyObjectData() method, which basically goes through the target object and copies any properties it can match from the source object. I have the same sort of thing for a DataRow object which guarantees that the data retrieved is in the proper update state.
So, am I off my nut? What are other people doing to pass data around and avoid having to write and re-write object parsing code each time?
Other Posts you might also like
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
- Getting the Client IP Address in ASP.NET Core
- Resolving Paths To Server Relative Paths in .NET Code
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Getting the ASP.NET Core Server Hosting Urls at Startup and in Requests
The Voices of Reason
# re: .Net Web Services and passing objects (and Data)
If I pass XML manaully I can at least fix this stuff or work around it.
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
Ultimately, you may want the same entity to be serialized in several formats depending on the application (security, etc). Why not create a declarative mapping file to map objects to xml? I think this is what the OSD mapping file is for (Object Schema Definition)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
> to pass data over the wire instead of
> objects?
This is what I've seen most .NET developers doing.
> I mean this completely goes counter the
> whole OO paradigm of dealing with data in
> the first place.
Yup.
> The Proxy approach works well in true
> disconnected to the server scenarios, but
> it's not a good match for side by side
> applications which in my work tends to be
> the more common case.
Have you tried with Remoting? I thought Remoting does "deep serialization" and you wouldn't run into these issues -- but I really haven't tried it.
# re: .Net Web Services and passing objects (and Data)
Let say i have a custom dll and i am adding the reference to the same in both client app and webservice everythign is fine here.BVut when i am assign the object of the same from the proxy to our object in client it didnot allow as it didnot consider the object same from the same class when it come thru proxy.
Here i had 2 options use the proxy object's object only by using some thing like
localhost.websrvnm.clscustom proxy=new localhost.websrvnm.clscustom
and
localhost.clscustom obj =new localhost.clscustom
then obj=proxy.method (which return the class type)
However the same is fine with interface approach in remoting.The question is why it is not so in webservice while i made a search i found this answer which is much closer taht is
since the contact for webservice is wsdl which didnot understand the class we are providing the mismatch occurs.
Any comments are welcome
# re: .Net Web Services and passing objects (and Data)
any comments are welcome
sndshreeman@rediffmail.com
# re: .Net Web Services and passing objects (and Data)
Alternately some functionality that can copy object data would be very welcome to at least make the job of pulling the data out of a proxy into the real object.
# re: .Net Web Services and passing objects (and Data)
My solution was to serialize the objects to and from the Web Service. So I always pass out and in a Binary String. I then de-Serialize the object on the other side and Voila -- I have my original object with all its properties in tact.
Passing DataSets to me is quite insecure as it gives your entire data Schema to hackers. Binary Serialization makes the web Service act more like a business layer as opposed to an inter-operable middle-tier. So if your intention is to work with other languages, then this is NOT the option for you. XMLSerilization may be better.
Hope that explanation helps. If anyone needs a code example, just holler back.
# re: .Net Web Services and passing objects (and Data)
Couple of things in this: You are passing strings? Are you sure? I think you mean passing byte arrays? Additionally realize that binary serialization does not serialize DataSets as binary, but still as XML! The reason it is not in the clear is because it's base64 encoded in your case which is not really difficult to undo! So, this is no security at all - if you need security make sure you run over HTTPS.
# re: .Net Web Services and passing objects (and Data)
Serialize the proxy classes to XML using the XmlSerializer, then Deserialize to business objects using the XML. Since the proxy object is XmlSerialized from the business object on the server, the Xml schema should be the same.
It's kind of sad to be forced to do this, but it works. I am still looking for a better approach.
# re: .Net Web Services and passing objects (and Data)
I do agree with casie,rick and the trick all we follow is somehow use serilization one end and deserialize at the other.I discussed the same with ms people and what explanation i got is this a architectural design decision that what webserviec meant for is passing the data in xml format from one endpoint to other and it is not recommended for type sharing etc.,
After i went thru few more blogs and articles i agree with them .
The problem is still there and will be there for more time i guess as we are thinking in oops way that is passing and sharing data and we are right since we are on n tier distributed arc but they are asking for SOA and aspect orientation.They are right in a way if we see the purpose of webservice but still we need some more improvement specifically on serialization issues ..
hope that serialization and validation will be incorporated in webservice soon.
# re: .Net Web Services and passing objects (and Data)
This is really a use case issue, IMHO. 90% of the time you will want to serialize/deserialize a type. So why should this not be supported in some way (and I'm not saying that this is should be the default)? I could see the argument if the way the implementation proxy would be completely immune to OOP version issues, but the proxy is created from the real type underneath it and so the main reason to stay with a SOA type message - version independence - isn't even served either.
Ulimately I think the real solution to this problem would be better support for copying of objects in the framework. Being able to take the message and more generically assign it to an object would serve both practicality and the 'purists' who want to preserve the message as a pure message mechanism. I have my own code to do this, but it feels like a hack - at least if the framework supported this it would be an 'official' hack <g>...
# re: .Net Web Services and passing objects (and Data)
Agree with you that "as it is" serialization should occurs and better mechanism should be provided from MS as they have now converted the WS more then "simple" message 'xml' transfer that is if we are not passing the and geting data then it is not worth for us.
however still webservice can't be a pure oop in the sense that type sharing is a probelm and further the gotcha is not a single vendor is creating the client and server.
also my point is that they should ship some standard on the same.
But i didn't get ur point on "In stock .NET 1.1 you can't even pass messages in any other way than to use objects "
we could pass dataset and xml compliance variables say string..as well as objects from service to client which will be accessible thorough the proxy though with limitation and with lost originality from the parent class... and though i m not favour of typed dataset...the point however is that how can we put them in an SOA model and AOP.
Very much agree with you on the similar copy topic and furtrher on why should we create serialization/deserialization always or why should we modify the generated proxy r create our custom one using soapclient protocol.
do update me as well whenever u found something update on same.
thanks
shreeman
sndshreeman@rediffmail.com
# re: .Net Web Services and passing objects (and Data)
I also think it makes no sense to say that because we're using objects to insinuate that that automatically won't fit with SOA. Microsoft has always used the object as the mechanism to translate and if proper serialization is added as a (optional) feature it won't affect the messages on the wire. The raw Web Service logic isn't affected, only how that data is generated and optionally consumed from our own code. Since most Web Services are internal and likely controlled by the same entity even this makes a lot of sense.
Again, I think the better way to solve this for Microsoft maybe just to provide better tools to copy objects or provide serialization in a way that doesn't have to map 1->1. This is basically how my routines work - they allow some flexibility, so if there are properties that exist on the proxy but not on the imported object or vice versa these properties are ignored. This provides the version flexibility that you would otherwise have to code anyway...
# Manually modify the generated client-side proxy classes?
Of course the down side to this is that if (when) I regenerate the proxy due to additions to the web service (I've really just started coding it), I will have to manually reapply my changes. Perhaps I'll try to write a VS.NET macro for this...
# re: .Net Web Services and passing objects (and Data)
However, if you require duplicate copies of objects being used by webservice *and* your client, something is wrong. The logic to operate on those entities should reside with the webservice server, not on the client. If the client can operate on the objects themselves, then why are you using webservices?
I think perhaps if one examines the functionality of the objects in question it will become clear that some things clearly belong as a webservice and other things clearly can (or should) be handled on the client.
People are passing around Datasets because this makes a good parameter passing mechanism in the case of complex sets of data between a service and a client.
There is a tendency to see everything as a nail when one has a hammer, and perhaps that is the case here with webservices.
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
While I agree to some extent I think it's silly to say - this class belongs to the Web Service and therefore you have to manage how to get data out of it. While that certainly could and probably should be the default the 90% plus scenario will be that you'll load this data into an object that has the exact same structure! So now you're writing manual process code to property mapping, right? Over and over again for every object that passes data over the wire? No way... this process should be automated.
It doesn't even matter whether this object runs in .NET, Java or Visual FoxPro. Those other tools will have to have their own mechanism, but in .NET regardless of whether you're a SOA purist or not - you get back an object. An object that on its own is nothing more than a data container that you can't do anything with other than copy it.
What I propose is that there should be an easy way to copy objects. That way the infrastructure can stay as it is, and those that need it can easily and effectively copy objects from one structure into another. There could be additional options for skipping members that don't match on both ends without failing. As I said above I do this now manually but it'd be much nicer if this was part of the framework.
Looking at my Web Services I see that well over 90% are one to one matches of object to what goes over the wire. I don't think I'm unique in this - this is the 90% use case.
# re: .Net Web Services and passing objects (and Data)
Your issue is valid, I can not speak for most but the best solution to date I have decided on - is to write a code generator that reads my database and creates transport objects - where by they seralize properly and move the data from one end to the other leaving me an object on the other end. I want to believe that datasets are the right way to handle this delima but the fact that Java does not happily work together or even recognize the format (the famous :any dilema) means that datasets say to the world you only care about .NET (which is fine but seems like it only serves to be a bandaid) I am not a huge fan of typed-datasets because I like my model to float from version to version leaving the client operable.
A classic issue to a standard still adapting to change.
# re: .Net Web Services and passing objects (and Data)
Explaination:
I have a class named UserInfo which represents a table named UserInfo. It contains user loginid and password as properties which are the fields of the table UserInfo. Now i have to pass this information as an object to a method called CheckLogin in webservices and return an object which contains the login success status to the client depending on which i will display a relevent message on the login page.The problem lies with serialization/deserialization.
Hope this info is sufient to understnd the problem..
Kindly get back to me as soon as possible..Its very urgent..Please Help!!
Thank you in Advance,
Archana
# re: .Net Web Services and passing objects (and Data)
From reading this...it sound like I can either serialize and then deserialize on the other end OR edit the Reference.cs to just pass through that type rather than a new Web Service Instance of it.
As another note, if you create more than one .asmx and pass the same object to the client from two different .asmx, they also have different namespaces and can't be cast to one generic object on the client side. So if you grab for instance a Person object from one .asmx and then pass it to another, you need to do what Rick was saying about Copying to the other object type. This causes all sorts of problems with when you add new properties remembering to add them to tyour Copy functions! Again, you could get round this by editing the namepaces in the Reference.cs.
Does anyone know of a way of editing how the Reference.cs is created?
I use NullableTypes and when you pass these through in an object, the 'using NullableTypes' doesn't get added and we currently use a text replace script to enter these in. But there must be an easier way surely! Maybe a template or something?
Thanks for all your ideas!
Jeremy
# re: .Net Web Services and passing objects (and Data)
In order to solve this problem I have been considering writing the same 'cheesy Reflection based CopyObjectData() method'. In my situation the server has a copy of all of the classes that are on the client (a PPC in my case) so there will be guarenteed a 100% match between members between the client and the server. This has the effect of moving the problem half a step sideways since I need to first copy the server object into the server implementation of the client object, send the client object through the pipe and then do a CopyObjectData at the client in to the final client implementation of the client object.
The idea of moving datasets through SOAP does not sit well with me. It may be good for simple solutions or where there is only a couple of SOAP calls but I am working on large enterprise projects in which everything is as strongly typed and as OO as possible and there is a lot of communication over SOAP. This philosophy applies to interprocess communications and as a result we run smack into the problem beign discussed.
# re: .Net Web Services and passing objects (and Data)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnservice/html/service07162002.asp
Hope it helps someone.
Metro.
# re: .Net Web Services and passing objects (and Data)
First go to your buisness objects, and make sure they are marked [Serializable()]. You might consider giving them an xml namespace (all the same ns) as well as making sure all your webservices have the same namespace. I'm not sure if the namespace bit is required, but it's what I did.
Next go to the generated Reference.cs file (you may need to hit the button to show all files)and add in the namespace(s) of your buisness objects (the dll(s) have to be referenced in the project, obviously). Then scroll down in the Reference.cs file and start deleting the auto-generated stubs for your buisness objects (just the object class definitions, dont delete anything else).
Thats it; compile away. If you have a second webservice do the same in it. Now you can pass objects from one webservice to the next, etc etc, just like you thought you were going to be able to do in the first place.
Note that your buisness objects may behave irreguarly if you attempt to call database functions when no database is availible, so a little caution or foresight in design is needed. Also note that every time you update your web reference in visual studio it will regenerate the Reference.cs file, and you will need to redo your changes. (Or do as I did and write your own little program to generate the Reference.cs file to use your buisness objects and save yourself the hassle)
--zack
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
http://west-wind.com/weblog/posts/9213.aspx
# re: .Net Web Services and passing objects (and Data)
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://MyWebService/GetPerson")]
public BusinessObjects.Person GetPerson()
{
//Note - weird aspect of invoke is it only works if the method name it is called from
// is the same as the method it is calling. i.e. if this method was called something
// other than GetPerson the Invoke would fail.
object[] results = this.Invoke("GetPerson", new object[0]);
return ((BusinessObjects.Person)(results[0]));
}
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
So if you're building a completely thin client then yeah it makes sense to not have a heavy business object on the client, but otherwise - it makes sense. I suspect there are a LOTS of applications that actually work in such an environment. In a pure thin client environment message objects as is are probably sufficient. Still even there it can be useful to have more full features business functionality like access to validation rules and other business operation.
FWIW, WCF address this scenario a lot better by allowing you to define a [DataContract] explicitly.
http://www.west-wind.com/WebLog/posts/9213.aspx
and you can share those message types on both ends of the connection which solves this problem to a large degree.
Ultimately though I think that what would be really nice if the framework had some generic mechanism for copying objects based on structure so that you can more easily map one object to another explicitly.
# re: .Net Web Services and passing objects (and Data)
The posting by Metro Sauper May 19, 2006, pointed to MSDN, and following that link which is now at the location below, I think I've found a solution, at least for a simple class that has nothing but value types and get/sets for all properties.
http://msdn.microsoft.com/en-us/library/aa480505.aspx
Some manual voodoo is required but it only took a minute. The biggest issue I see is trying to remember this pattern for all projects. If it turns out to be inefficient or otherwise ineffective, I'll post back here, but I encourage everyone to just try out the technique described and let's see where it goes.
# re: .Net Web Services and passing objects (and Data)
RIA Services does this very nicely. Now we don't need to do the plumbing ourselves.
Check it out at:
http://www.microsoft.com/downloads/details.aspx?FamilyID=76bb3a07-3846-4564-b0c3-27972bcaabce&displaylang=en
# re: .Net Web Services and passing objects (and Data)
With vbscript and COM+ I could create an instance of an object on a completely different computer with: -
Server.CreateObject("SomeDistributedObject")
and an instance exists with all the properties and methods.
with Web Services, not only do you need a copy of an assembly on both the server and client (versioning issues), you need to add an intermediate stage of populating a new instance of an object from the returned data, or deserialize an object passed.
Either way, there is no longer a central point where the class exists and can be referenced from anywhere. instead, it's a clumsy system of redistributing an assembly, to all dependents, whenever a change has been made.
Hello Java.
# Question
# re: .Net Web Services and passing objects (and Data)
# re: .Net Web Services and passing objects (and Data)
/// <summary>
/// Attempt to convert one object to another via deserialization
/// </summary>
/// <typeparam name="T">Destination type</typeparam>
/// <param name="target">Object to convert</param>
/// <returns>A new object of the Destination type</returns>
public static T convert<T>( object target ) where T : new()
{
T returnValue;
try
{
XmlDocument sourceDocument = serialize( target );
XmlAttribute attribute = sourceDocument.CreateAttribute("xmlns");
attribute.Value = getSerializedNamespace( typeof(T) );
sourceDocument.DocumentElement.SetAttributeNode(attribute);
returnValue = deSerialize<T>( sourceDocument );
}
catch
{
returnValue = new T();
}
return returnValue;
}
/// <summary>
/// Serializes an object to an XML string
/// </summary>
/// <param name="target">Object to be serialized</param>
/// <returns>string containing the serialized object</returns>
public static string serializeToString( object target )
{
return serializeToString( target, null );
}
/// <summary>
/// Serializes an object to an XML string
/// </summary>
/// <param name="target">Object to be serialized</param>
/// <param name="namespaces">Namespaces to add to the document</param>
/// <returns>string containing the serialized object</returns>
public static string serializeToString( object target, XmlSerializerNamespaces namespaces )
{
string returnValue = null;
if ( null != target )
{
XmlSerializer serializer = new XmlSerializer( target.GetType() );
using (MemoryStream stream = new MemoryStream())
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
using (XmlWriter writer = XmlWriter.Create( stream, settings ))
{
if ( null != namespaces )
{
serializer.Serialize( writer, target, namespaces );
}
else
{
serializer.Serialize( writer, target );
}
}
returnValue = Encoding.UTF8.GetString( stream.ToArray() ).Trim();
}
}
return returnValue;
}
/// <summary>
/// Serialize an object to an XML Document
/// </summary>
/// <param name="target">Object to be serialized</param>
/// <returns>XmlDocument containing the serialized object</returns>
public static XmlDocument serialize( object target )
{
XmlDocument returnValue = new XmlDocument();
if ( null != target )
{
returnValue.LoadXml( serializeToString( target ) );
}
return returnValue;
}
/// <summary>
/// Factory method for deserializing an object from an XML document
/// </summary>
/// <param name="sourceDocument">document to deserialize</param>
/// <returns>Object from deserialized XML Document</returns>
public static T deSerialize<T>( XmlDocument sourceDocument )
{
T returnValue;
XmlSerializer deserializer = new XmlSerializer( typeof(T) );
using (MemoryStream stream = new MemoryStream( Encoding.UTF8.GetBytes( sourceDocument.DocumentElement.OuterXml ) ))
{
object result = deserializer.Deserialize( stream );
returnValue = (T) result;
}
return returnValue;
}
/// <summary>
/// Gets the namespace an object will use for serialization
/// </summary>
/// <param name="objectType">Type to get the namesapce from</param>
/// <returns>String containing the Namespace used for serialization</returns>
public static string getSerializedNamespace( Type objectType )
{
string returnValue = objectType.Namespace;
Attribute[] attributes = Attribute.GetCustomAttributes( objectType );
foreach ( Attribute attribute in attributes )
{
if ( attribute is XmlTypeAttribute )
{
XmlTypeAttribute xmlType = (XmlTypeAttribute) attribute;
returnValue = xmlType.Namespace;
break;
}
}
return returnValue;
}
}
Note: The code isn't fully tested. It's just an example.
# re: .Net Web Services and passing objects (and Data)
What I tend to do is pass objects as XML string around. Even when using .Net on both the server and client side this gives a better performance than passing DataSet objects. Why this is I don’t know but this is true both with Web Services and Remoting.
With my own objects I tend to put these in a separate, shared, DLL and include a ToXml and FromXml function to facilitate the conversion. Yes this means I have to do some additional stuff each time I pass an object around but at least I get a real object on the client instead of some generated proxy object. An additional benefit I only discovered later was that not all DataSets can be serialized. Adding RowError information is enough to trip the normal serialization done by web services.
Maurice