Serialization - WebApi for WCF with base type property (abstract)

2

I have a problem here where I have a WebApi consuming a WCF. Basically I'm having trouble receiving a WCF property that is the base type of the class I'm actually sending. I'll give you an example to make it easier to explain:

    
[DataContract]
[KnownType(typeof(EnderNacional))]
[KnownType(typeof(EnderInternacional))]
public abstract class EnderBase
{
    [DataMember]
    public String Logradouro { get; set; }
    ///...
}

[DataContract]
public class EnderNacional : EnderBase
{
    public String Cep { get; set; }
    ///...
}

[DataContract]
public class EnderInternacional : EnderBase
{
    [DataMember]
    public String CodigoPostal { get; set; }
    ///...

}

[DataContract]
[KnownType(typeof(CliNacional))]
[KnownType(typeof(CliInternacional))]
public abstract class CliBase
{
    [DataMember]
    public String Nome { get; set; }
    [DataMember]
    public IEnumerable<EnderBase> Enderecos { get; set; }
    ///...
}

[DataContract]
public class CliNacional : CliBase
{
    [DataMember]
    public String Cnpj { get; set; }
}

[DataContract]
public class CliInternacional : CliBase
{
    [DataMember]
    public String Identificacao { get; set; }
}

Here I put an example of a national and international client class, which inherits from a base class. The same happens with addresses where national and international exist, inheriting from base class to address. For those of you who have worked with WCF you have certainly had the problem with abstract classes and therefore the use of " KnownType " for WCF to serialize the passed object.

[ServiceContract]
public interface IServiceClientes
{
    [OperationContract]
    int SalvarNacional(ServiceClientes.CliNacional cliente);
}

public class ServiceClientes : IServiceClientes
{
    public int SalvarNacional(Clientes.CliNacional cliente)
    {
        //...código
        return int.MinValue;
    }
}

The above code is a representation of the implementation of IServiceClients .

This works fine when I test directly through WCFTestClient.exe , when I give the address, the EnderNational and EnderInternational also appears to choose . So, just choose one, fill in the information and that's it, C # can serialize the object because it knows that type, thanks to KnownType . I know there are other ways and even dynamics to do this but that's beside the point.

My problem starts when I use a WebApi to consume this method and make it available to Clients . Example:

[HttpPost]
    public HttpResponseMessage SalvarClienteNacional(Api.CliNacional clienteNacional)
    {
        return Request.CreateResponse(HttpStatusCode.OK, new MyService.ServiceClientesClient().SalvarNacional(clienteNacional));
    }

Here is a simple example of a call to my WCF through WebApi, assuming that MyService is my properly mapped WCF service.

When I test WebApi, the JSON object is correctly sent to my " ClientNational " parameter, but it comes with the " Addresses " property mapped such as " EnderBase " and when this is sent to WCF I get an exception that it is not possible to instantiate an abstract class.

WCF probably can not understand that my JSON represents a national or international address, or because the "Addresses" property is mapped to the base class, which is really abstract! At the time of cast it seems that it tries to instantiate the collection type itself, generating the exception.

p>

What could I do to solve this problem? Has anyone had a similar problem?

Any and all help is welcome.

Thanks to everyone in advance.

    
asked by anonymous 17.07.2014 / 19:01

1 answer

1

You followed the right steps, you probably forgot the other parts.

1) You've reviewed the WCF in isolation. No difference in behavior, which works with WCFTestClient, works anywhere. But be aware, there are chances that you have changed your WCF and have not regenerated your Service Reference.

2) You said you looked at Json, Ok, but did you analyze what Model Binder actually delivered to your controller? Use brakepoints to validate if your object is arriving at your Action correctly, it is very likely that in your WebApi deserialization your problem may be the absence of specific attributes for the WebApi Model Binder.

3) You can see that you are using the same class your service uses in your WebApi. Well, to serve as a mere proxy, without any intelligence, there is no need for WebApi. Using a correct WCF binding would securely host what you need.

[] 's

    
12.08.2014 / 06:12