Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
540 views
in Technique[技术] by (71.8m points)

c# - Web Api Model Binding and Polymorphic Inheritance

I am asking if anyone knows if it is possible to to pass into a Web Api a concrete class that inherits from a abstract class.

For example:

public abstract class A
{
    A();
}

public class B : A
{
}

[POST("api/Request/{a}")]
public class Request(A a)
{
}

At present I have looked around and most solutions seem to say that using TypeNameHandling will work.

JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;

However this is not that case. Also my model is being passed from a console app to the webapi. I have read that I may be able to deserialize the json object and after attempting this a few times I decide this was not going to work.

I have looked into creating a customer model binder however, I do not want to make my application more complex that it has to be. At present I inherit from the abstract class with 3 models but may in the future extend this. As you may note adding custom model binders may require multiple binders unless there is a way of making one binder generic for all types of the abstract class.

To expand on this in my console app I have instantiated class b as such and then passed it to the ObjectContent before posting to my webapi

item = B();

//serialize and post to web api
MediaTypeFormatter formatter;
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
formatter = jsonFormatter;

_content = new ObjectContent<A>(item, formatter);
var response = _client.PostAsync("api/Request", _content).Result;

when the webapi action is called the object is null

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If one really wanted to implement what is asked in the question, there is a custom way to do it.

First, create a custom json converter that is inherited from JsonConverter, in it pick a target class and deserialize an instance.

Then, in your WebApiConfig.Register you add your new converter into config.Formatters.JsonFormatter.SerializerSettings.Converters and enjoy this monstrosity in action.

Should you do it? No.

Understanding how to use such API will bring no joy to any new users, documenting this will not be easy, and most importantly - there are no benefits in implementing it this way. If input types are different, then they deserve separate API methods with different URLs. If only few properties are different - make them optional.

Why the example did not work? The TypeNameHandling is from Json.NET, Web API knows nothing about it, and type information is not part of the JSON spec, so there is no standard way to solve this particular issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...