Search code examples
c#.net.net-coreinterface

Deserialization of Inteface types not supported in API Request


I am getting this error message:

System.NotSupportedException: Deserialization of interface types is not supported.

while calling an API which taken request as per below:

example

[HttpPost]
public IActionResult AddSomeData(MyClass MyClass)
{
   return Ok();
} 

public class MyClass : MyInterface
{
   return Ok();
}

public interface MyInterface 
{
    public string SomeOtherProperties { get; set; }

    public MyInterface Property { get; set; } //Or reference of any other interface
}

I have tried examples given online, like creating Concrete Class and adding attribute over the property, but it is not helping out.

As workaround I have removed public MyInterface Property { get; set; } and added public MyClass Property { get; set; }.

Any better solution for this?


Solution

  • The problem with deserializing to an interface is that you lose information

    public class MyClass : MyInterface
    {
        public string SomeOtherProperties { get; set; }
        public MyInterface Property { get; set; }
        public string importantString { get; set; } = "Don't lose me please";
    }
    
    public interface MyInterface
    {
        string SomeOtherProperties { get; set; }
        MyInterface Property { get; set; }
    }
    

    Take the above example, trying to deserialize to the interface would involve telling the deserializer to only know about the properties on the interface - and any other fields your end user is supplying getting dropped entirely. On top of that you might have methods on the concrete class that support the interface properties that need to exist.

    There are some options involving reflection that you could use if you need the API to support multiple implementations of an interface, but the question is why you need the interface in the first place? An API is supposed to cleanly define what needs to be supplied by the user, abstracting that with an interface that needs to be implemented by some mystery concrete class seems like a bad idea.

    Edit: if all you need is the shared information and there isn't anything fancy - you could just use MyInterface as a standard class

    public class MyClass : MyInterface
    {
        public string nonImportantString { get; set; } = "lose me";
    }
    public class MyInterface
    {
        public  string SomeOtherProperties { get; set; }
        public  MyInterface Property { get; set; }
    }
    

    In doing so your api is clean, and you can deserialize fine