Created
August 15, 2020 00:25
-
-
Save natenho/1d1f9b726af6b419f043497bdd961907 to your computer and use it in GitHub Desktop.
Allow a controller method receive both single or multiple models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Mvc.Formatters; | |
using Microsoft.Extensions.Logging; | |
using Microsoft.Net.Http.Headers; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Microsoft.AspNetCore.Mvc.Formatters | |
{ | |
/// <summary> | |
/// Allow a controller method receive both single or multiple models | |
/// </summary> | |
/// <seealso cref="http://scottclewell.com/post/multiple-or-single-aspnetcore/"/> | |
public class SingleOrMultipleInputFormatter<T> : TextInputFormatter | |
{ | |
public SingleOrMultipleInputFormatter() | |
{ | |
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json")); | |
SupportedEncodings.Add(Encoding.UTF8); | |
SupportedEncodings.Add(Encoding.Unicode); | |
} | |
protected override bool CanReadType(Type type) | |
{ | |
return typeof(IEnumerable<T>).IsAssignableFrom(type); | |
} | |
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) | |
{ | |
var logger = context.HttpContext.RequestServices.GetService(typeof(ILogger<SingleOrMultipleInputFormatter<T>>)) as ILogger; | |
var request = context.HttpContext.Request; | |
using (var reader = context.ReaderFactory(request.Body, encoding)) | |
using (var jsonReader = new JsonTextReader(reader)) | |
{ | |
// Important: Don't close the request stream because you many need it in other middleware or controllers. | |
jsonReader.CloseInput = false; | |
var succeeded = true; | |
object model = null; | |
try | |
{ | |
var token = JToken.Load(jsonReader); | |
if (token.Type == JTokenType.Array) | |
{ | |
model = token.ToObject<IEnumerable<T>>(); | |
} | |
else | |
{ | |
var single = token.ToObject<T>(); | |
model = new[] { single }; | |
} | |
} | |
catch (Exception ex) | |
{ | |
logger.LogError(ex, "Error parsing model"); | |
succeeded = false; | |
} | |
if (!succeeded) | |
{ | |
return await InputFormatterResult.FailureAsync(); | |
} | |
if (model == null && !context.TreatEmptyInputAsDefaultValue) | |
{ | |
return await InputFormatterResult.NoValueAsync(); | |
} | |
return await InputFormatterResult.SuccessAsync(model); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment