locked
How to share class file in Silverlight client code and server code? RRS feed

  • Question

  • I'm serializing a class to xml on server-side, sending xml stream to silverlight client, then deserialize it on client side. The problem I have is I have to make two same data contract class, both on server-side and client-side. Is it possible to write a class library which you can include in both silverlight and ASP.NET server project? [DataContract(Name = "ImageDTO", Namespace = "http://localhost")]

    public class ImageDTO
    {
        [DataMember()]
        public string name { get; set; }
        [DataMember()]
        public string fileName { get; set; }
        [DataMember()]
        public string uri { get; set; }

    }

    Tuesday, July 8, 2008 7:29 AM

Answers

  • I'm not sure about sharing a class library but another solution would be that instead of sending the data as an XML stream, if you expose it as a web service and then create a service reference to it from your Silverlight app, then you have full class typing available to the Silverlight app through the reference.  It sounds like that would give you exactly what you are asking for.

    Tuesday, July 8, 2008 8:14 AM
  • I agree with John's suggestion (use a Web Service), but the question is still semi-valid for other reasons.

    For example, you might have a class on the server which has a computed property, and you'd like that same computed property on the client side. You could just mark it as a [DataMember] but then it would get serialised across the wire. If it's a computed property then it seems a little wasteful to send the value across the wire. I realise that generally a web-service is not intended to replicate implementation, but that seems to be to be a suggestion aimed at those consuming external web services. There is also a whole class of applications where one development team controls both sides of the implementation (client and server) and if code-sharing makes life simpler, I see nothing wrong with that.

    In answer to the original question, a couple of proposals:

    Can you use partial classes and conditional compilation to intelligently split up the implementation of the class so that the client gets the "Shared" part of the implementation and the server what extra features it requires in its own partial class? And if the client needs special features that can also be a partial class?

    Keep in mind you cannot share an assembly per se because Silverlight assemblies are compiled differently to conventional .NET assemblies.

    Tuesday, July 8, 2008 8:24 AM
  • I'm serializing a class to xml on server-side, sending xml stream to silverlight client, then deserialize it on client side. The problem I have is I have to make two same data contract class, both on server-side and client-side. Is it possible to write a class library which you can include in both silverlight and ASP.NET server project? [DataContract(Name = "ImageDTO", Namespace = "http://localhost")]

    public class ImageDTO
    {
        [DataMember()]
        public string name { get; set; }
        [DataMember()]
        public string fileName { get; set; }
        [DataMember()]
        public string uri { get; set; }

    }



    If you use WCF to do this. It would be much easier. Once you add Service Reference to your Silverlight project, a proxy class is generated in your Silverlight project so the DataContract class you defined in the Server side can be accessed from Silverlight side. You use the same syntxt to access the class on both sides. You do not need to write any code to do serialization/deseirialization. The WCF will do it for you.

     

     

     

    Tuesday, July 8, 2008 11:09 AM
  • I think you're probably right that using WCF probably takes care of his needs better, provided he's just looking to get the data structure and none of the behavior code.

    But he'd still get a data structure if he was using an asmx web service.  He must have some reason for explicity serializing to/from XML.

    renshao, where is that XML coming from?  Even if it's not a service call, you could set up a service reference in your silverlight project just to get the DataContracts on both sides.

    Tuesday, July 8, 2008 2:10 PM
  • Yes, for this simple object, using asmx web service works the same by just adding a service reference.


     

    Tuesday, July 8, 2008 5:59 PM

All replies

  • I'm not sure about sharing a class library but another solution would be that instead of sending the data as an XML stream, if you expose it as a web service and then create a service reference to it from your Silverlight app, then you have full class typing available to the Silverlight app through the reference.  It sounds like that would give you exactly what you are asking for.

    Tuesday, July 8, 2008 8:14 AM
  • I agree with John's suggestion (use a Web Service), but the question is still semi-valid for other reasons.

    For example, you might have a class on the server which has a computed property, and you'd like that same computed property on the client side. You could just mark it as a [DataMember] but then it would get serialised across the wire. If it's a computed property then it seems a little wasteful to send the value across the wire. I realise that generally a web-service is not intended to replicate implementation, but that seems to be to be a suggestion aimed at those consuming external web services. There is also a whole class of applications where one development team controls both sides of the implementation (client and server) and if code-sharing makes life simpler, I see nothing wrong with that.

    In answer to the original question, a couple of proposals:

    Can you use partial classes and conditional compilation to intelligently split up the implementation of the class so that the client gets the "Shared" part of the implementation and the server what extra features it requires in its own partial class? And if the client needs special features that can also be a partial class?

    Keep in mind you cannot share an assembly per se because Silverlight assemblies are compiled differently to conventional .NET assemblies.

    Tuesday, July 8, 2008 8:24 AM
  • I also subscribe to this pattern.  There are times when I want shared logic between server and client side and I want to serialize those objects directly.

    Despite the popularity of SOA, %90 percent of the web service code I write has well-defined server and client endpoints that one team controls - these services are not meant for generic consumption.  Too often, I think SOA-style code isn't worth the cost and results in too much actual business logic being tied too closely to the UI.  I prefer to keep a set of business objects that are usable client side that encapsulate the use of the web service proxy as a transport layer, that simply maps to the methods in the DAL.
    </rant>

     With silverlight, you just can't share assembly.  Your best bet is probably to use your source control system to share the class files between two projects.  I especially like Kevmeister's partial class suggestion.

     It's more work than just sharing an assembly, but it's the next best thing - you're still sharing code.  You just have to be especially careful that developers know that changing the file in the server project automatically updates the client project and vice versa or you can have unexpected consequences.  You also have to watch out for versioning issues if you have a situation where client and server can be using different versions of the code.

    That's probably not an issue in Silverlight since you have complete control of how and when the client is deployed.

    Tuesday, July 8, 2008 8:59 AM
  • Thanks guys.

    I'll try that partial class strategy. Big Smile

    As in Java, you can simply serialise the objects and send the stream to client.Both client and server can share a single class file.

    I'm expecting Microsoft to come up with something to address this issue.

    Tuesday, July 8, 2008 10:28 AM
  • Thanks guys.

    I'll try that partial class strategy. Big Smile

    As in Java, you can simply serialise the objects and send the stream to client.Both client and server can share a single class file.

    I'm expecting Microsoft to come up with something to address this issue.

     

    I think it is not about anything special in java, but java has nothing like Sliverlight. If a java class requires a third party component on server side, it won't run on client side unless the client side has the same component.

    To the original question, I think we really need "include" in C/C++ back. Maybe some one can come up with a pre-processor for C#.

    Tuesday, July 8, 2008 10:55 AM
  • I'm serializing a class to xml on server-side, sending xml stream to silverlight client, then deserialize it on client side. The problem I have is I have to make two same data contract class, both on server-side and client-side. Is it possible to write a class library which you can include in both silverlight and ASP.NET server project? [DataContract(Name = "ImageDTO", Namespace = "http://localhost")]

    public class ImageDTO
    {
        [DataMember()]
        public string name { get; set; }
        [DataMember()]
        public string fileName { get; set; }
        [DataMember()]
        public string uri { get; set; }

    }



    If you use WCF to do this. It would be much easier. Once you add Service Reference to your Silverlight project, a proxy class is generated in your Silverlight project so the DataContract class you defined in the Server side can be accessed from Silverlight side. You use the same syntxt to access the class on both sides. You do not need to write any code to do serialization/deseirialization. The WCF will do it for you.

     

     

     

    Tuesday, July 8, 2008 11:09 AM
  • I think you're probably right that using WCF probably takes care of his needs better, provided he's just looking to get the data structure and none of the behavior code.

    But he'd still get a data structure if he was using an asmx web service.  He must have some reason for explicity serializing to/from XML.

    renshao, where is that XML coming from?  Even if it's not a service call, you could set up a service reference in your silverlight project just to get the DataContracts on both sides.

    Tuesday, July 8, 2008 2:10 PM
  • Yes, for this simple object, using asmx web service works the same by just adding a service reference.


     

    Tuesday, July 8, 2008 5:59 PM
  • Thankk guys, again.

    I'm learning WCF now, and I think using WCF would solve my problem.

    Cheers.

    Sunday, July 13, 2008 1:35 AM
  • I've just finished posting a blog entry on this subject.

     

    Tuesday, July 29, 2008 4:55 PM
  •  There was a suggestion about using partial classes, but no code examples, so I'm posting one I did awhile ago (before I came to this thread). The following works for me...

     (Moved to blog post: http://jameswilkins.net/coding/silverlight/54)




    Thursday, February 19, 2009 5:22 AM
  • jamesnw, I am probably missing something very obvious, but the example you provided above will not work when !SILVERLIGHT condition is false (i.e. when the 'data contract' part of it compiles out), because there would be no 'Ok', 'UserName', etc. properties in existence...

    Could you please clarify?

     

    Also, I have a (probably very stupid) question: how do you "reconcile" this class with the one provided by the auto-generated WCF service reference (from Reference.cs file)?  When you make a call to some method to, say, get an instance of your data class, the service client helper will return the class from Reference.cs -- do you just manually convert that into your own (new) CPPLoginState instance, property-by-property (or e.g. via a copy constructor), or am I missing, again, something really obvious?

     

    Thanks in advance,

    Tim

    Friday, April 17, 2009 5:48 PM
  •  Because "[DataContract]" is specified, the class will exist at both the server side (where it is defined) and the client side (where it gets "copied" to). The class exists, on both sides, as a "partial" class. Now, on the server, the fields are declared by the class (as shown); however, when the class is move to the client via the "references.cs" file, the fields are ALREADY declared (because they were marked with "[DataMember]"), so the compiler directives are needed to skip that part.

     I think you need to read up on what a "partial" class is to get more insight, but basically, they get merged together into a single class - hence, there is no "reconciliation" needed.

     The great thing about partial classes, in this case, is that I could define a class method that works at both ends for my data objects (as long as the code is compatible on both ends [on both CLRs]). :)

    Hope that helps.

    Friday, April 17, 2009 7:10 PM
  • Thanks for your post. 
    There is a problem unfortunately. If a class contains a list<> of another class (and these are not subject to export through methods WCF) then you can not apply your excellent method). I do not know if I explained well.
    Tuesday, May 5, 2009 12:08 PM
  • The way I've worked with when I want to share code between server and client side is by having a short cut of the server side .cs file into my SL project and it just work fantastic.

    I don't need to post much about it because there is blog entry from Tim that I'd read long time :-)

     

    Wednesday, May 6, 2009 12:34 AM
  • ...which was mentioned in my post already. :P  :)

    Wednesday, May 6, 2009 12:56 AM
  • sharing doesn't work well because if your data class defines attributes like [range] or [display], these attributes will not be passed to client via serviceReference.... 

    Monday, September 20, 2010 2:17 PM
  • If you are building a Silverlight application, I'd suggest focusing on what Silverlight can do and not your web service. Personally, I've switch to RIA services now, which I am finding much better support for code sharing across the projects. In either case, you should build your "shared" objects and logic on Silverlight, and then use "#if !SILVERLIGHT" compiler directives to strip out anything the web service doesn't need to care about. Trying to "dumb down" your code is much harder than starting at the lower end and working up.

    Monday, September 20, 2010 2:30 PM