Avrohom Yisroel
Avrohom Yisroel

Reputation: 9440

Exception with ServiceKnownType when the WCF method returns a collection

I have a base class Fallible<T> and several derived classes Success<T>, Failure<T> and BadIdea<T> which are to be used in the return value of a WCF service call.

As I previously discovered, in order to get this to work, I needed to decorate the WCF service method with the ServiceKnownType attribute as follows...

[OperationContract]
[ServiceKnownType(typeof(Fallible<Patient>)]
[ServiceKnownType(typeof(Success<Patient>)]
[ServiceKnownType(typeof(BadIdea<Patient>)]
[ServiceKnownType(typeof(Failure<Patient>)]
public Fallible<Patient> GetPatient(int id) {
  return new Success<Patient>(new Patient {ID = 1,FirstName = "Jim",Surname = "Spriggs"});
}

This works fine. However, I now want a WCF service method that returns a collection...

public List<Patient> GetDischargedPatients()

Following what I did before, I tried decorating this, but no matter what combination I tried, I get exceptions. Here is the full combination of what I tried...

[OperationContract]
[ServiceKnownType(typeof(Fallible<PatientOverview>))]
[ServiceKnownType(typeof(Success<PatientOverview>))]
[ServiceKnownType(typeof(BadIdea<PatientOverview>))]
[ServiceKnownType(typeof(Failure<PatientOverview>))]
[ServiceKnownType(typeof(Fallible<PatientOverview[]>))]
[ServiceKnownType(typeof(Success<PatientOverview[]>))]
[ServiceKnownType(typeof(BadIdea<PatientOverview[]>))]
[ServiceKnownType(typeof(Failure<PatientOverview[]>))]
[ServiceKnownType(typeof(List<Fallible<PatientOverview>>))]
[ServiceKnownType(typeof(List<Success<PatientOverview>>))]
[ServiceKnownType(typeof(List<BadIdea<PatientOverview>>))]
[ServiceKnownType(typeof(List<Failure<PatientOverview>>))]
public Fallible<List<PatientOverview>> GetDischargedPatients() {
  return new Success<List<PatientOverview>>();
}

As you can see, I've thrown everything in there (except what actually works!), but I still get the original exception I got before discovering the ServiceKnownType attribute...

"An error occurred while receiving the HTTP response to http://localhost:5448/PatientsService.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details."

Inner exception:

"The underlying connection was closed: An unexpected error occurred on a receive."

Inner exception:

"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."

Inner exception:

"An existing connection was forcibly closed by the remote host"

WCF really isn't giving me any information about what's going wrong here. I tried using ServiceKnownType with various combinations of the return type, including Fallible<Patient[]> and Fallible<List<Patient>> but it didn't help.

Anyone any ideas what I need to do to return a collection?

Upvotes: 2

Views: 381

Answers (2)

Scrobi
Scrobi

Reputation: 1215

So I tried to replicate your issue with a trimmed down version of your code and ended up with this

[ServiceContract]
public interface IService1
{
     //Get a patient's data
    [OperationContract]
    [ServiceKnownType(typeof(Fallible<Patient>))]
    [ServiceKnownType(typeof(Success<Patient>))]
    Fallible<Patient> GetPatient(int id);

     //Get a list of Patients
    [OperationContract]
    List<Patient> GetPatients();

    //Get a list of patients
    [OperationContract]
    [ServiceKnownType(typeof(Fallible<List<Patient>>))]
    [ServiceKnownType(typeof(Success<List<Patient>>))]
    Fallible<List<Patient>> GetSpecificPatients(string type);
}

and the implementation of the service:

public class Service : IService1
{
    public Fallible<Patient> GetPatient(int id)
    {
        return new Success<Patient>() { Value = new Patient() { Name = "Scott Robinson" } };
    }

    public List<Patient> GetPatients()
    {
        List<Patient> patients = new List<Patient>();
        patients.Add(new Patient() { Name = "Scott Robinson" });
        patients.Add(new Patient() { Name = "Darryl Robinson" });
        return patients;
    }

    public Fallible<List<Patient>> GetSpecificPatients(string type)
    {
        switch (type)
        {
            case "Fallible":
                return new Fallible<List<Patient>>() { Value = new List<Patient>() { new Patient() { Name = "Scott" }, new Patient() { Name = "Darryl" } } };              
            default:
                return new Success<List<Patient>>() { Value = new List<Patient>() { new Patient() { Name = "Scott" }, new Patient() { Name = "Darryl" } } };
        }
    }
}

However I do not get the error.

Looking at your code I can see that your GetDiscardedPatients returns Fallible<List<PatientOverview>> but none of the 'ServiceKnownTypes` are of this type. Have you tried:

ServiceKnownType[Fallible<List<PatientOverview>>]
ServiceKnownType[Success<List<PatientOverview>>]
...
public Fallible<List<PatientOverview>> GetDischargedPatients() {
  return new Success<List<PatientOverview>>();
}

Upvotes: 2

Hicham Bouchikhi
Hicham Bouchikhi

Reputation: 726

[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(CommandServiceHelper))]
public interface IPatientService
{
     //Your interface methdos
}

this is the helper class that will be called each time that WCF need to know a type.

public static class CommandServiceHelper
{
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
    {
        //Return a list of type that your service will need to know 
    }
}

And if you need more detail and explanation you can check this blog post by Mebyon Kernow.

Upvotes: 0

Related Questions