PetaPoco - Including Custom Partial Class Properties in WCF Response - wcf

I have been experimenting with using PetaPoco for a small project I am working, and it has been awesome so far.
I have created some additional, non auto-generated partial classes to hold various computed values, as shown in my example below. I can't get these additional properties to be serialized into a WCF response, but all of the properties in the auto-generated stuff serializes just fine. I tried using [Serializable] and [DataContract] on these custom properties, but they break the WCF service altogether.
Any ideas?
public partial class Session
{
[ResultColumn]
public int ConnectedUserCount
{
get
{
AssistedServiceDB db = new AssistedServiceDB();
return db.ExecuteScalar<int>("SELECT Count(*) FROM Session_AssistedServiceUser WHERE IsConnected = 1");
}
}

There are couple of things to look to get partial WCF DataContracts to work. First, if the other Session class is marked with the DataContract then this class would also need to be marked the same way. This is assuming the ResultSession class is also serializable and/or marked as DataContract. The other issue is WCF requires properties to, as a minimum, have private setters so the ConnectedUserCount property needs to be changed to have one.

Related

DataContract properties names during proxy generation with svcutil

Is there any switch that instructs svcutil to generate DataContract properties with their names as defined in code? For example when I create a proxy which uses the following DataContract:
[DataContract(Namespace = "http://schemas.mynamespace.com/2012/08")]
public class MyDataContract
{
[DataMember(IsRequired = true, Order = 0)]
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
}
I get this DataContract on the proxy generated class:
public partial class MyDataContract : object
{
private int _idField;
[System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]
public int _id
{
get
{
return this._idField;
}
set
{
this._idField = value;
}
}
}
The order property of the DataMemberAttribute is always ommited as well for the first 3 properties and a MessageContract ommits an IDisposable implementation.
Well, I cannot comment on the omitted order, but I may be able to help on the rest:
One usually specifies the DataMember attribute on the property, not on the field. The data-contract itself does not distinguish between a property and a field, but it knows the name, type, if it is mandatory, etc. etc.
Added: What Chris said: With [DataMember(Name="whateveryouwant")] you'll be able to set a name different from the field/property name. I do not like such usage, though, but it is helpful when refactoring code, but still keeping the API compatible.
Only other DataContract (and some intrinsically supported) types are serialized to/from messages. IDisposable seems not to be one.
Serializing the inherited IDisposable of a MessageContract would not make any sense. A message-contract is the .NET representation of a SOAP message. It literally has nothing else to do but to provide a 1:1 mapping between what is in the SOAP message XML, and the accessible .NET types.
A message is part of a ServiceContract, in that it specifies which kind of message must be sent to a certain operation to be a valid invocation, and another (response-)message contract specifies how the data, that the operation returns, will be structured. Nothing else; it is a data-aggregate.
If you want to capture the result of a service-operation on the client, and for convenience automatically send a message back upon going out of scope (or for instance unregistering from a service), you will have to implement this on the client-side. Be aware, however, that the service must not require this to happen (due to lost connections, crashes, etc.).
Use the name property on DataMember attribute
Such as:
[DataMember(Name="myname")]

WCF - Return object without serializing?

One of my WCF functions returns an object that has a member variable of a type from another library that is beyond my control. I cannot decorate that library's classes. In fact, I cannot even use DataContractSurrogate because the library's classes have private member variables that are essential to operation (i.e. if I return the object without those private member variables, the public properties throw exceptions).
If I say that interoperability for this particular method is not needed (at least until the owners of this library can revise to make their objects serializable), is it possible for me to use WCF to return this object such that it can at least be consumed by a .NET client?
How do I go about doing that?
Update: I am adding pseudo code below...
// My code, I have control
[DataContract]
public class MyObject
{
private TheirObject theirObject;
[DataMember]
public int SomeNumber
{
get { return theirObject.SomeNumber; } // public property exposed
private set { }
}
}
// Their code, I have no control
public class TheirObject
{
private TheirOtherObject theirOtherObject;
public int SomeNumber
{
get { return theirOtherObject.SomeOtherProperty; }
set { // ... }
}
}
I've tried adding DataMember to my instance of their object, making it public, using a DataContractSurrogate, and even manually streaming the object. In all cases, I get some error that eventually leads back to their object not being explicitly serializable.
Sure, write a wrapper class that has all of the same public properties available and simply put "get { return internalObject.ThisProperty; }. Decorate the wrapper class so that it works with WCF.
Another option is to write a Proxy class which mirrors the properties of the type you wish to use exactly, and return that via WCF.
You can use AutoMapper to populate the proxy object.
This approach has the advantage that your service's consumers don't need to take a dependency on the third party library in trying to use it.

WCF with shared objects and derived classes on client

I have a WCF service and I'm sharing types with a client in a shared assembly.
If the client create a derived class will it be possible to pass back the derived type to the service so that I can read the added properties through reflection ?
I tried but having issues with KnownTypes since the service don't know how to deserialize the derived type.
[Serializable]
public abstract class Car : ICar
{........
//on the client :
[Serializable]
public class MyCar : Car
{......
when passing myCar to Service I get the exception complaining about knownType but I cant add this on the server since I wont know what the client will be sending through and I want to handle extra properties through reflection.
Possible to register client types as knowntypes at runtime ?
Is this maybe the solution ?
http://blogs.msdn.com/b/sowmy/archive/2006/03/26/561188.aspx
This is not possible. Both service and client has to know what types will be sent in messages. If you want to use known type you have to define that relation to parent type on the service.
Why do you need to know added properties on the server?
I think there is a way.
I vaguely remember that when I studied WCF, I met ExtensionData which should be a mechanism to get everything that does not match the serialization of the class. for example, if you enable ExtensionData and you are in this situation
//Server
public class GenericRQ
{
public string GenericProperty {get;set;}
}
public Service GenericService
{
Public void GenericMethod(GenericRQ RQ)
{
}
}
// client
Public class MoreSpecificRQ : GenericRQ
{
public string SpecificProperty {get;set;}
}
At
Public void GenericMethod(GenericRQ RQ)
{
// the serializer adds automatically in RQ.ExtensionData everything that has come and that does not match the class GenericRQ.
}
On how to enable ExtensionData you to easily search on the web

WCF DataContract Upcasting

I'm trying to take a datacontract object that I received on the server, do some manipulation on it and then return an upcasted version of it however it doesn't seem to be working. I can get it to work by using the KnownType or ServiceKnownType attributes, but I don't want to roundtrip all of the data. Below is an example:
[DataContract]
public class MyBaseObject
{
[DataMember]
public int Id { get; set; }
}
[DataContract]
public class MyDerivedObject : MyBaseObject
{
[DataMember]
public string Name { get; set; }
}
[ServiceContract(Namespace = "http://My.Web.Service")]
public interface IServiceProvider
{
[OperationContract]
List<MyBaseObject> SaveMyObjects(List<MyDerivedObject> myDerivedObjects);
}
public class ServiceProvider : IServiceProvider
{
public List<MyBaseObject> SaveMyObjects(List<MyDerivedObject> myDerivedObjects)
{
... do some work ...
myDerivedObjects[0].Id = 123;
myDerivedObjects[1].Id = 456;
myDerivedObjects[2].Id = 789;
... do some work ...
return myDerivedObjects.Cast<MyBaseObject>().ToList();
}
}
Anybody have any ideas how to get this to work without having to recreate new objects or using the KnownType attributes?
I think that your problem is that you are trying to send over a generic list.
It will work if you encapsulate the list in an object. That is create an object with a single public property which is the generic list.
You also need to make sure that all classes that are not used directly in the contract are marked as serializable.
If you want to return the derived objects then there will always be a round trip because the client and the service are separate. In order for the client to update its own list of MyBaseObjects it has to deserialize the list of MyDerivedObjects that came from the server.
The use of KnownType and/or ServiceKnownType is needed because this leads to the addition of that type information into WSDL, which is in turn used by the client to deserialize the messages to the correct type.
For starters, a useful tool for testing the scenario you've described: http://www.wcfstorm.com
You might try creating a DataContractSurrogate (IDataContractSurrogate) and returning your base type for the call to GetDataContractType. I'm not really sure that's how it was intended to be used so you still may be better of with "the extra work", but maybe I don't understand the scope of that extra work.
One of the problems with WCF (and .net remoting) is that it they tries to make “message passing” look like method calls.
This fall down when you try to use too many “oop” type designs.
The fact that the messages are
represented by .net classes, does not
make all of their behaviour like .net
class.
See this, and this, for more on the problem of Leaking Abstraction.
So you need to start thinking about message passing not object when designing your WCF interfaces, or you will hit lots of problems like this.

Is it possible to serialize objects without a parameterless constructor in WCF?

I know that a private parameterless constructor works but what about an object with no parameterless constructors?
I would like to expose types from a third party library so I have no control over the type definitions.
If there is a way what is the easiest? E.g. I don't what to have to create a sub type.
Edit:
What I'm looking for is something like the level of customization shown here: http://msdn.microsoft.com/en-us/magazine/cc163902.aspx
although I don't want to have to resort to streams to serialize/deserialize.
You can't really make arbitrary types serializable; in some cases (XmlSerializer, for example) the runtime exposes options to spoof the attributes. But DataContractSerializer doesn't allow this. Feasible options:
hide the classes behind your own types that are serializable (lots of work)
provide binary formatter surrogates (yeuch)
write your own serialization core (a lot of work to get right)
Essentially, if something isn't designed for serialization, very little of the framework will let you serialize it.
I just ran a little test, using a WCF Service that returns an basic object that does not have a default constructor.
//[DataContract]
//[Serializable]
public class MyObject
{
public MyObject(string _name)
{
Name = _name;
}
//[DataMember]
public string Name { get; set; }
//[DataMember]
public string Address { get; set; }
}
Here is what the service looks like:
public class MyService : IMyService
{
#region IMyService Members
public MyObject GetByName(string _name)
{
return new MyObject(_name) { Address = "Test Address" };
}
#endregion
}
This actually works, as long as MyObject is either a [DataContract] or [Serializable]. Interestingly, it doesn't seem to need the default constructor on the client side. There is a related post here:
How does WCF deserialization instantiate objects without calling a constructor?
I am not a WCF expert but it is unlikely that they support serialization on a constructor with arbitrary types. Namely because what would they pass in for values? You could pass null for reference types and empty values for structs. But what good would a type be that could be constructed with completely empty data?
I think you are stuck with 1 of 2 options
Sub class the type in question and pass appropriate default values to the non-parameterless constructor
Create a type that exists soley for serialization. Once completed it can create an instance of the original type that you are interested in. It is a bridge of sorts.
Personally I would go for #2. Make the class a data only structure and optimize it for serialization and factory purposes.