Pergunta

I tried to minimize writing of code for WCF CRUD part of big project with use of generics and castle WCF facility.

I have 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 generic 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 WCF client in Windsor Container

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

Everythig is working fine, components and services registered, controller created properly, service

readonly ICRUDService<T> service;

in controller is of type

Castle.Proxies.IResourceService 

But when i try to use service in controller i have 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 controller i hardcode cast

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

all is running properly, so i believe this problem is solvable.

I've also tried to use Forward (with same result) :

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

How to make it work?

Foi útil?

Solução

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

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

with generic implementation

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

in standard way (for multiple 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 fileless activation in web.config

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

On server side it works perfectly. Sadly on client side i didn't found working solution for WCFFacility and i had to use ChannelFactory (which is working perfectly)

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

For the rest (standard non generic services i'm using WCF Facility without any problems.

Outras dicas

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top