Configure input/output formatters on controllers with ASP.NET Core 2.1

前端 未结 2 1127
予麋鹿
予麋鹿 2020-12-20 05:43

I am in the process of rewriting an old ASP.NET WebAPI 2.1 project to ASP.NET Core MVC 2.1. One of the problem I am facing is about porting the old behavior of the service w

相关标签:
2条回答
  • 2020-12-20 06:10

    Actually I found a way. I created an attribute which also implements IResultFilter and here is the OnResultExecuting method, where the magic happens:

    public void OnResultExecuting(ResultExecutingContext context)
    {
      var objectResult = context.Result as ObjectResult;
      if (objectResult != null)
      {
        var serializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new DefaultContractResolver()
        };
    
        var jsonFormatter = new JsonOutputFormatter(
            serializerSettings,
            ArrayPool<char>.Shared);
    
        objectResult.Formatters.Add(jsonFormatter);
      }
    }
    

    Basically here I am injecting a custom JSON formatter in every object result, before it is sent to the client. It appears (but I did not find any documentation about this) that in this way ASP.NET Core MVC prefers the injected formatter over the globally defined one.

    I hopes it helps other because I was struggling on this...

    0 讨论(0)
  • 2020-12-20 06:26

    I haven't found anything that can be configured at the controller level, but I did find a solution that involves changes to each action where you need this functionality. In my case I needed to customize the JSON serializer settings, which can be done like this for the output:

    [HttpGet]
    public IActionResult Get()
    {
        ...
        return Json(result, _serializerSettings);
    }
    

    and like this for input:

    [HttpPost]
    public IActionResult Post([FromBodyCustomSerializationSettings]MyPostDto postDto)
    {
        ...
    }
    
    class FromBodyCustomSerializationSettingsAttribute : ModelBinderAttribute
    {
        public FromBodyCustomSerializationSettingsAttribute() : base(typeof(MyModelBinder))
        {
            BindingSource = BindingSource.Body;
        }
    }
    
    class MyModelBinder : IModelBinder
    {
        private readonly BodyModelBinder _bodyModelBinder;
    
        public MyModelBinder(IHttpRequestStreamReaderFactory readerFactory, ILoggerFactory loggerFactory, IOptions<MvcOptions> options, IOptions<MvcJsonOptions> jsonOptions, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider)
        {
            var formatters = options.Value.InputFormatters.ToList();
            int jsonFormatterIndex = formatters.FirstIndexOf(formatter => formatter is JsonInputFormatter);
            JsonSerializerSettings myCustomSettings = ...
            formatters[jsonFormatterIndex] = new JsonInputFormatter(loggerFactory.CreateLogger("MyCustomJsonFormatter"), myCustomSettings, charPool, objectPoolProvider, options.Value, jsonOptions.Value);
            _bodyModelBinder = new BodyModelBinder(formatters, readerFactory, loggerFactory, options.Value);
        }
    
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            return _bodyModelBinder.BindModelAsync(bindingContext);
        }
    }
    
    0 讨论(0)
提交回复
热议问题