Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exposing WCF subclasses based on an abstract class

I have an abstract class which I would like to be able to expose to WCF so that any subclasses will also be able to be started as a WCF service.
This is what I have so far:

[ServiceContract(Name = "PeopleManager", Namespace = "http://localhost:8001/People")]
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[DataContract(Namespace="http://localhost:8001/People")]
[KnownType(typeof(Child))]
public abstract class Parent
{
    [OperationContract]
    [WebInvoke(Method = "PUT", UriTemplate = "{name}/{description}")]
    public abstract int CreatePerson(string name, string description);

    [OperationContract]
    [WebGet(UriTemplate = "Person/{id}")]
    public abstract Person GetPerson(int id);
}

public class Child : Parent
{
    public int CreatePerson(string name, string description){...}
    public Person GetPerson(int id){...}
}

When trying to create the service in my code I use this method:

public static void RunService()
{
    Type t = typeof(Parent); //or typeof(Child)
    ServiceHost svcHost = new ServiceHost(t, new Uri("http://localhost:8001/People"));
    svcHost.AddServiceEndpoint(t, new BasicHttpBinding(), "Basic");
    svcHost.Open();
}

When using Parent as the type of service I get
The contract name 'Parent' could not be found in the list of contracts implemented by the service 'Parent'. OR Service implementation type is an interface or abstract class and no implementation object was provided.

and when using the Child as the type of service I get
The service class of type Namespace.Child both defines a ServiceContract and inherits a ServiceContract from type Namespace.Parent. Contract inheritance can only be used among interface types. If a class is marked with ServiceContractAttribute, then another service class cannot derive from it.

Is there a way to expose the functions in the Child class so I don't have to specifically add the WCF attributes?

Edit
So this

[ServiceContract(Name= "WCF_Mate", Namespace="http://localhost:8001/People")]  
    public interface IWcfClass{}  

    public abstract class Parent : IWcfClass {...}  
    public class Child : Parent, IWcfClass {...}

with starting the service with Child returns
The contract type Namespace.Child is not attributed with ServiceContractAttribute. In order to define a valid contract, the specified type (either contract interface or service class) must be attributed with ServiceContractAttribute.

like image 837
bju1046 Avatar asked Feb 28 '23 23:02

bju1046


1 Answers

The service contract is usually an interface, not a class. Place your contract into an interface, have the abstract class implement this interface, and let us know what happens when you use Child to start the service.

Edit: Ok, now you need to modify your RunService method to this below. The contract type if IWcfClass, not Child or Parent.

public static void RunService()
{
        Type t = typeof(Child);
        ServiceHost svcHost = new ServiceHost(t, new Uri("http://localhost:8001/People"));
        svcHost.AddServiceEndpoint(typeof(IWcfClass), new BasicHttpBinding(), "Basic");
        svcHost.Open();
}
like image 111
Szymon Rozga Avatar answered Mar 11 '23 08:03

Szymon Rozga