Serialization - Webapi for WCF with base type property (Abstract)

Asked

Viewed 383 times

2

I have a problem here where I have a Webapi consuming a WCF. I’m basically having trouble getting into WCF a property that’s the base type of class I’m actually sending. I’ll set 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 inherit from a base class. The same happens with addresses where there are national and international inheriting from base class to address. For those who have worked with WCF certainly have had the problem with abstract classes and so the use of "Knowntype" so that WCF can serialize the object passed.

[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 Iserviceclientes.

This works well when I test directly by Wcftestclient.exe, when I will inform the address, also appears the Endernacional and Enderinternational for choice. So, just choose one of the two, 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 this is not the case.

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 the Webapi, assuming that Myservice is my properly mapped WCF service.

When I test the Webapi, correctly sent the JSON object I get it correctly in my parameter "national clientele", but the same comes with the property "Addresses" mapped as "Enderbase" and when this is sent to the WCF I receive an Exception that it is not possible to instantiate an abstract class.

Probably the WCF cannot understand that my JSON represents a national or international address or because the "Addressees" property is mapped as being the base class, which is really abstract! At the time of the cast it seems that it attempts to instantiate the Collection type itself, generating Exception.

Googlei enough and only find the same solution I’m already using, which is the use of Knowntype but it seems that this worked only when I use WCF classes directly, not when cast through a JSON.

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

Any and all help is welcome.

I bless you all in advance.

1 answer

1

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

1) You have analyzed WCF a little in isolation. There is no difference in behavior, what works with Wcftestclient, works anywhere. But stay tuned, there are chances you have changed your WCF and not have regenerated your Service Reference.

2) You said you analyzed Json, OK, but you analyzed what Model Binder actually delivered to your controller? Use brakepoints to validate if your object is getting to your Action correctly, it is very likely that it is in the deserialization of the Webapi your problem, it is possible that it is the absence of specific attributes for the Webapi Model Binder.

3) You can see that you are using the same class that 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 Binding for WCF you hostel safely what you need.

[ ]'s

  • Regarding the 3 items: 1) I will govern my service yes; 2) in the Webapi I checked yes the structure of the object and was ok, IE, json for the api was not in trouble. But I don’t know what these attributes are specific to the Model Binder, could you help me? 3) This structure of having a Webapi was client’s requirement, where the WCF would be only local and only the Web visible Api.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.