This is my ABC on the server side:
<endpoint address="msmq.formatname:DIRECT=OS:.\private$\imhmsgs"
binding="msmqIntegrationBinding"
bindingConfiguration="IncomingMessageHandlerBinding"
contract="TMC.Services.Contracts.Messages.IInboundMessageHandlerService">
As soon as I do an .Open() to host the service, I get the exception:
Cannot serialize interface
XYZ.Services.Contracts.Messages.Interfaces.IMyMessage.
My IMyMessage interface:
[ServiceContract]
[ServiceKnownType(typeof(IMyMessage))]
[ServiceKnownType(typeof(ConcreteMessage))]
public interface IInboundMessageHandlerService
{
[OperationContract(IsOneWay = true, Action = "*")]
void ProcessIncomingMessage(MsmqMessage<IMyMessage> incomingMessage);
}
The implementor for that interface:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
ReleaseServiceInstanceOnTransactionComplete = false)]
public class InboundMessageHandlerService : IInboundMessageHandlerService
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void ProcessIncomingMessage(MsmqMessage<IMyMessage> incomingMessage)
{
}
}
The type that is being created by the client basically is a concrete class, which derives from a base class and also an interface (IMyMessage) and then places this on the MSMQ.
After some testing, if I remove the service known type attributes and just instead use say "string" instead, then it seems to open the host but faults (because the message type is not what it was expecting).
where am I going wrong?
On further testing I see that if I only specify the concrete type, it works.
This is not quite what I was expecting.
how am I able to create it so that the service can take a known interface and classes which that interface has? The idea is for the client (using the same contract and classes) to send the message as "IMyMessage" and for the WCF service to pick that up as "IMyMessage" and go ahead and find out the type of message/object it is.
How?
Your contract is an interface, but the definition within the contract must be concrete classes.
In your case it looks like you want to send over a list of things, those things could be different but they all support the same interface.
The problem is that when WCF deserialises what has been sent over the wire, it needs to deserialise it the a concrete type. If it just has an interface in the definition and 20 different types that implement that definition, it does not know what to do with it.
What you can do is have a base type that implements the interface, all your classes inherit from the base type and you use the base type in your contact.
Related
I am trying to consume WCF in my MVC web app. I have implemented the channel factory for instantiating the proxy client.
I am stuck at a point. Here is the code highlight -
I created a proxy base class where i am creating the channel :
public abstract class ServiceProxyBase<T> : IDisposable where T : class
For creating teh proxy wrapper class i have inherited this base class as :
public class ProxyWrapper : ServiceProxyBase<IMyService>,IMyService
Here "IMyService" is the WCf contract.
Now, in the controllers i have added overloaded constructors as :
public class AccountController : Controller
{
private IMyService businessService;
public AccountController(IMyService _businessService)
{
this.businessService = _businessService;
}
}
For injecting dependency I have included unity.mvc4 package.
It works fine when I am using the following code :
container.RegisterType<IMyService, ProxyWrapper>();
This works as long as the ProxyWrapper is inheriting the IMyService interface directly. If i remove the inheritance like
public class ProxyWrapper : ServiceProxyBase<IMyService>
it gives an error while registering type.
I would like to have a way without inherting the contract in the proxy wrapper. I have spent almost a day trying to fix this. But am able to figure out a solution.
Please give your valuable suggestions on this.
If I understand correctly, your application is using a WCF service but the functionality your application needs is limited compared to the functionality that the service offers (it contains more methods than you need). According to the Interface Segregation Principle, "no client should be forced to depend on methods it does not use" and the Dependency Inversion Principle states that clients own the abstraction.
In other words, you should define your own interface that the application should use and define an implementation that wraps (i.e. composition over inheritance) the generated WCF proxy class.
For instance:
public interface IMyApplicationService
{
object GetStuff();
void PutStuff(object instance);
}
public class MyServiceApplicationProxy : IMyApplicationService
{
private readonly ProxyWrapper wcfProxy;
public MyServiceApplicationProxy(ProxyWrapper wcfProxy) {
this.wcfProxy = wcfProxy;
}
public object GetStuff() {
return this.wcfProxy.GetStuff();
}
public void PutStuff(object instance) {
this.wcfProxy.PutStuff(instance);
}
}
To make application development easier, makes your code easier to read, maintain and test.
You might even want to change the methods of your interface to better suit your application needs. Remember: the client defines the interface! So that might mean that you need to do more mapping inside the MyServiceApplicationProxy class to map adapt your core domain to the contract of the external web service. Don't let the external WCF service's contract leak into your core domain.
Can we two WCF services where one service contract derives from another and have an extension method inside the derived contract. what will be the result of accessing this contract from the WCF Client. I.e. what will happen if IDServiceis accessed
E.g.
[ServiceContract]
public interface IBaseService
{
public void A();
...
}
[ServiceContract]
public interface IDService: IBaseService
{
public static void B(this IBaseService S);
....
}
You can't define static methods in an interface (nor the access modifier public which you've specified above either).
A good question - got me to a lot of head scratching.
Extension method is meaningless to WCF - and WSDL for that matter.
If you use Service Reference to generated the client, you would not see the extension method (since WSDL would not know anything about the extension method) so you cannot use it.
If you use DLL/Project reference, your code will be called locally and not through the proxy.
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
I have a WCF service and have to expose an interface as datacontract. There are two derived classes from the interface.
The WCF service will return an object of the derived type.The client will have to cast it as a derived class. Is that possible on the client side ?.What should be my approach.
If you have derived classes, you need to "advertise" those on the data contract:
[DataContract]
[KnownType(typeof(DerivedType1))]
[KnownType(typeof(DerivedType2))]
public class BaseType
{
......
}
or you can also specify these kind of relations on a service contract:
[ServiceKnownType(typeof(DerivedType1))]
[ServiceKnownType(typeof(DerivedType2))]
[ServiceContract()]
public interface IService
{
[OperationContract]
BaseType GetItems();
}
Check out the MSDN docs on Data Contract Known Types or Service Known Types for more background info.
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.