Reputation: 2214
is it possible to have an api endpoint whose method's sign can accepts a parameter that can be a single object or a collection of objects?
i have a method like this:
[HttpPost, Route("DoSomething")]
public async Task<IHttpActionResult> DoSomething([FromBody] MyType xxx, CancellationToken cancel)
i need to modify this method to accept a collection of MyType class (an array, enumerable, list... doesn't matter)
[HttpPost, Route("DoSomething")]
public async Task<IHttpActionResult> DoSomething([FromBody] IEnumerable<MyType> xxx, CancellationToken cancel)
anyway for a little while the client that calls this endpoint will continue to send me a single object { }
and not a collection of objects [{ },{ }]
is it possible to modify this endpoint to accept both types?
Upvotes: 0
Views: 205
Reputation: 118957
You can do this with a custom JsonConverter
. For example, this should work, or at least be enough for you to customise:
public class SingleOrListConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(List<T>);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T>
{
token.ToObject<T>()
};
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Now you add it to your configuration. In Global.asax.cs
, add this line:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters
.Add(new SingleOrListConverter<string>());
Now just use a single endpoint:
public async Task<IHttpActionResult> DoSomething(
[FromBody] IEnumerable<MyType> xxx, CancellationToken cancel)
Upvotes: 1
Reputation: 7171
I think 2 solutions:
Accepet the data as string
, and you can parse it yourself in any way, you can process the string, give it different rules to judge which type it should be convert, e.g. if contains [
then parse it as List, otherwise a single object.
Write 2 methods one accept List another Single Obj, and write usage clearly in api documentation, then provide the document to the user.
Upvotes: 0