WCF Facility lock, using a universal interface for a non-general contract

I tried to minimize code entry for the WCF CRUD part of a large project using generics and a WCF lock object.

I have a WCF service contract:

[ServiceContract] public interface IResourceService : ICRUDService<DTOResource> { [OperationContract] DTOResource Get(long id); } 

and generic interface

 public interface ICRUDService<T> where T is IDTO { T Get(long id); } 

also a common MVC controller (1 controller for all basic crud for dtos and services)

 public class CRUDController<T> : Controller where T is IDTO { readonly ICRUDService<T> service; public CRUDController(ICRUDService<T> service) { this.service = service; } } 

On the client side, I register the WCF client in the Windsor Container

 Component .For<IResourceService , ICRUDService<DTOResource>>() .AsWcfClient(... standard stuff... ) 

Everythig works fine, components and services are registered, the controller is created correctly, services

 readonly ICRUDService<T> service; 

in the controller is of type

 Castle.Proxies.IResourceService 

But when I try to use the service in the controller, I have an error

 Method Get is not supported on this proxy, this can happen if the method is not marked with OperationContractAttribute or if the interface type is not marked with ServiceContractAttribute. 

When in the controller I hardcode cast

 ((IResourceService)service).Get(id); 

everything is working fine, so I believe this problem is solvable.

I also tried using Forward (with the same result):

 Component .For<IActionTypeService> .Forward<ICRUDService<DTOResource>>().AsWcfClient(... 

How to make it work?

+4
source share
2 answers

In the end, I had to use Channel Factory on the client side. I was able to use Windsor WCF Facility on the server side to register a generic contract:

 [ServiceContract] public interface ICRUDService<I> { [OperationContract] I Get(int id); } 

with general implementation

 public class CRUDService<I, IEntity> : ServiceBase, ICRUDService<I> { public I Get(int id) { ... } 

in a standard way (for several types)

 private void InstallExample<I, IEntity>(IWindsorContainer container) { container.Register( Component .For<ICRUDService<I>>() .ImplementedBy(CRUDService<I, IEntity>) .Named("somename") .AsWcfService( new DefaultServiceModel() .Hosted() .PublishMetadata(x => x.EnableHttpGet()) .AddEndpoints(WcfEndpoint .BoundTo(new BasicHttpBinding()) .At("someAddress") ) ) .LifeStyle.PerWcfOperation(); } 

with unmanned activation in web.config

 <add factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" service="ClientService" relativeAddress="./ClientService.svc" /> 

On the server side, it works fine. Unfortunately, on the client side, I did not find a working solution for WCFFacility, and I had to use ChannelFactory (which works fine)

 ChannelFactory<ICRUDService<I>> factory = new ChannelFactory<ICRUDService<I>>(someBinding, someEndpoint); 

For the rest (standard non-shared services, I use WCF Facility without problems.

+2
source

I think you need to put the ServiceContract attribute in ICrudService <>, add an OperationContract to this method and remove the duplicate Get () declaration from the IResourceService.

+1
source

Source: https://habr.com/ru/post/1447221/


All Articles