WCF client proxy exception - "Type cannot be added to list of known types" - wcf

I am having problems creating WCF client proxy for service code like in this example:
// data classes
[KnownType(typeof(ClassA))]
[KnownType(typeof(ClassB))]
public abstract class BaseClass : Dictionary<string, ITest>
{
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
public interface ITest
{
}
// service
[ServiceContract]
public interface IService1
{
[OperationContract]
BaseClass Method();
}
public class Service1 : IService1
{
public BaseClass Method()
{
...
}
}
Whenever I try to create a WCF proxy using "Add Service Reference" in VS it fails and trace log says
Type 'WcfProxyTest.ClassA' cannot be added to list of known types since another type 'WcfProxyTest.ClassB' with the same data contract name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfKeyValueOfstringanyType' is already present. If there are different collections of a particular type - for example, List<Test> and Test[], they cannot both be added as known types. Consider specifying only one of these types for addition to the known types list.
I can see what the error message is saying, but is there any other way around this (other than refactoring the classes). I am dealing with a legacy system which has classes written in the same manner as in my example and rewriting them is not an option as this stuff sits in the very core of the system :S
Any ideas? Thanks!

I decided to refactor the code in such a way that I don't have to provide two KnownTypes which gets me around the problem. About 300 syntax errors later that worked. I would be interested in any other ways of doing it though...

Try adding:
[KnownType(typeof(Dictionary<string, ITest>))]

Related

Register WCF proxy wrapper using Unity

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.

Using Ninject to bind an interface to multiple implementations unknown at compile time

I just recently started using Ninject (v2.2.0.0) in my ASP.NET MVC 3 application. So far I'm thrilled with it, but I ran into a situation I can't seem to figure out.
What I'd like to do is bind an interface to concrete implementations and have Ninject be able to inject the concrete implementation into a constructor using a factory (that will also be registered with Ninject). The problem is that I'd like my constructor to reference the concrete type, not the interface.
Here is an example:
public class SomeInterfaceFactory<T> where T: ISomeInterface, new()
{
public T CreateInstance()
{
// Activation and initialization logic here
}
}
public interface ISomeInterface
{
}
public class SomeImplementationA : ISomeInterface
{
public string PropertyA { get; set; }
}
public class SomeImplementationB : ISomeInterface
{
public string PropertyB { get; set; }
}
public class Foo
{
public Foo(SomeImplementationA implA)
{
Console.WriteLine(implA.PropertyA);
}
}
public class Bar
{
public Bar(SomeImplementationB implB)
{
Console.WriteLine(implB.PropertyB);
}
}
Elsewhere, I'd like to bind using just the interface:
kernel.Bind<Foo>().ToSelf();
kernel.Bind<Bar>().ToSelf();
kernel.Bind(typeof(SomeInterfaceFactory<>)).ToSelf();
kernel.Bind<ISomeInterface>().To ...something that will create and use the factory
Then, when requesting an instance of Foo from Ninject, it would see that one of the constructors parameters implements a bound interface, fetch the factory, and instantiate the correct concrete type (SomeImplementationA) and pass it to Foo's constructor.
The reason behind this is that I will have many implementations of ISomeInterface and I'd prefer to avoid having to bind each one individually. Some of these implementations may not be known at compile time.
I tried using:
kernel.Bind<ISomeInterface>().ToProvider<SomeProvider>();
The provider retrieves the factory based on the requested service type then calls its CreateInstance method, returning the concrete type:
public class SomeProvider : Provider<ISomeInterface>
{
protected override ISomeInterface CreateInstance(IContext context)
{
var factory = context.Kernel.Get(typeof(SomeInterfaceFactory<>)
.MakeGenericType(context.Request.Service));
var method = factory.GetType().GetMethod("CreateInstance");
return (ISomeInterface)method.Invoke();
}
}
However, my provider was never invoked.
I'm curious if Ninject can support this situation and, if so, how I might go about solving this problem.
I hope this is enough information to explain my situation. Please let me know if I should elaborate further.
Thank you!
It seems you have misunderstood how ninject works. In case you create Foo it sees that it requires a SomeImplementationA and will try to create an instance for it. So you need to define a binding for SomeImplementationA and not for ISomeInterface.
Also most likely your implementation breaks the Dependency Inversion Princple because you rely upon concrete instances instead of abstractions.
The solution to register all similar types at once (and the prefered way to configure IoC containers) is to use configuration by conventions. See the Ninject.Extensions.Conventions extenstion.

Extension methods in a data contract

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.

WCF Versioning : Update Attribute Namespaces and Support Previous Namespaces

I have three WCF services (.svc) which generate .wsdl references for SOAP messages.
Given that part of the namespace needs to change for all ServiceContract, OperationContract, DataContract attributes, for example
[DataContract(Namespace = "http://old.com.au/types/")]
to
[DataContract(Namespace = "http://new.com.au/types/")]
How is it that I can still support clients which have the old service reference (without them needing to update, because maybe they wont have time to update immediately) and allow clients getting a new service reference to get the new namespace? None of the service is changing, just the namespace.
So far I have read a lot of stuff but the following article suggests it is possible to change the service type from the ServiceHostFactory : http://blog.ranamauro.com/2008/07/hosting-wcf-service-on-iis-site-with_25.html
Which would mean creating two of every contract (putting as much of the implementation as possible in one place), and figuring out at runtime which serivce type to use. This would create some mess in my scenario.
Q. Is there an alternative, nice way to accomplish this or is it expected that this kind of thing should not be done and the client made to update to the new namespace.
(If there is a namespace mismatch from the client I get the error : The message with Action "..." cannot be processed at the receiver, due to a ContractFilter mismatch)
IMO, you need to host old services for your previous clients at (preferably) old end points and have new services at new end points. You can take out old services when all your old clients migrate to newer version.
Perhaps, you can use inheritance to reduce your efforts, for example
[DataContract(OldNameSpace)]
ClassA {
...
}
[DataContract(NewNameSpace)]
ClassB : ClassA {
}
Similarly, create new service contract from inheriting from new one. Service implementation need not change expect it needs to implement new contract. Now you have to configure two end point - one for old contract and another for new contract.
Edit: Put sample interfaces and implementation
Let's say your old contract was something like
public interface IOldContract
{
ClassA GetFoo();
void DoBar(ClassA a);
}
Now you can choose the new contract either as
public interface INewContract
{
ClassB GetFoo();
void DoBar(ClassB b);
ClassB GetMix(ClassB a);
}
or as
public interface INewContract2 : IOldContract
{
ClassB GetFoo2();
void DoBar2(ClassB b);
ClassB GetMix2(ClassB b);
}
I tend to go with later variation (as new contract remains compatible with old one). But in your case, you can choose former as you will be anyway exposing two endpoints.
Now you need modify service implementation as follows:
public class ServiceImplementation : INewContract2
{
#region INewContract2 Members
public ClassB GetFoo2()
{
// Your old implementation goes here
}
public void DoBar2(ClassB b)
{
DoBar(b);
}
public ClassB GetMix2(ClassB b)
{
return GetMixHelper(b);
}
#endregion
#region IOldContract Members
public ClassA GetFoo()
{
return GetFoo2();
}
public void DoBar(ClassA a)
{
// You old implementation goes here
}
public ClassA GetMix(ClassA a)
{
return GetMixHelper(a);
}
#endregion
private ClassB GetMixHelper(ClassA a)
{
// Your old implementation goes here
}
}
I hope that you get the idea. Even here also you have multiple choices of code organization. You can have two skeleton service implementation classes - one for old contract and another for new contract. Both will delegate actually functionality to a helper class (which is your current implementation).

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