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.
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.
I have several WCF services that use the same dataContracts to interchange data between them.
Can I have a sort of Metadata Endpoint for centralizing the management of all this schemas?
When creating a new WCF service, how can i make it to load the schemas from the Metadata Endpoint (instead of redefining them) to use inside its operationContracts?
Thanks!
As I said in the comment, I'm not sure I understand your question (at least with regards to wanting a metadata endpoint), but it sounds like you want to have the ability to reuse existing data contracts in multiple different services.
The easiest way to do that is to put the data contracts in a separate assembly (class library - DLL), and then have the services reference that assembly - they don't have to be defined inside the service itself.
Here's a trivial example (code is for illustration only, not intended to actually do anything or be a complete sample):
MyDataContracts assembly
namespace MyDataContracts
{
[DataContract]
public class DataContract1
{
}
[DataContract]
public class DataContract2
{
}
}
MyService1 assembly
using MyDataContracts;
namespace MyService1
{
[ServiceContract]
public interface IMyService1
{
[OperationContract]
DataContract1 GetSomeData(string someParm);
}
}
MyService2 assembly
using MyDataContracts;
namespace MyService2
{
[ServiceContract]
public interface IMyService2
{
[OperationContract]
void SendSomeData(DataContract1 dc);
[OperationContract]
DataContract2 GetSomeOtherData(int parm);
}
}
Of course, each of the WCF service projects will need to include a reference to the MyDataContracts assembly as well.
Now whenever you create a new service, you simply add a reference to the MyDataContracts.dll and you can reuse your data contracts in it.
I have my service layer, entities and DTOS in a separeted assembly called CCL.Data
The problem:
All My application is referencing the service layer directly using interfaces and IoC.
For example, I have an interface in my CCL.Data assembly called ICustomerService it depends on ICustomerRepository that depends on MyContext. All my application is referencing ICustomerService to call its methods....... so far no problem.
So I created a WCF Project.... referencing CCL.Data in this project....
I create a new Service, but int this case below, I would need to change all points in my application that call ICustomerService to WCFCustomerServiceClient, does exists a better way without cause a big impact in my project?
[ServiceContract]
public interface IWCFCustomerService
{
[OperationContract]
CustomerDTO GetCustomerById(int id);
}
public class WCFCustomerService : IWCFCustomerService
{
ICustomerService _customerService;
public WCFCustomerService()
{
MyContext context = new MyContext();
ICustomerRepository customerRep = new CustomerRepository(context);
_customerService = new CustomerService(customerRep);
}
public CustomerDTO GetCustomerById(int id)
{
return _customerService.GetCustomerById(id);
}
}
Tks,
William
Do you need to redefine IWCFCustomerService in place of ICustomerService? Is it not possible just to add ServiceContract attributes to your original ICustomerService interface (they will just get ignored by non WCF code)? (Its true that this does give you a dependancy on ServiceModel - but I cant see a way out of that).
Note also that if you use a ServiceRefernce to generate proxy code then the code generated will include a your service interface in different namespace for use clientside. Its worth noting that your not abliged to use that version of the interface (which could be annoying if you have a proxy and not proxy implimentation) but can still use the org interface definition either from a dll or compiled into your 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
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>))]