在ASP.NET Core 2.1中配置控制器的输入/输出格式器

5

我正在将一个旧的ASP.NET WebAPI 2.1项目重写为ASP.NET Core MVC 2.1。我面临的问题之一是如何移植服务的旧行为,该服务通过实现IControllerConfiguration接口的自定义属性配置输入和输出格式化程序。我没有找到这个接口的替代品,也没有任何在控制器级别配置格式化程序的替代方法,除了使用AddMvc(options)方法在全局级别注入它们。

3个回答

6

我没有找到可以在控制器级别进行配置的任何内容,但我找到了一种解决方案,它涉及到需要此功能的每个操作的更改。 在我的情况下,我需要自定义JSON序列化程序设置,可以通过以下方式完成输出:

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

而对于输入,则可以这样:

[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);
    }
}

5

实际上我找到了一种方法。我创建了一个属性,它也实现了IResultFilter,并且在这里是OnResultExecuting方法,奇迹就发生了:

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);
  }
}

基本上,我在将每个对象结果发送到客户端之前,都要注入自定义的JSON格式化程序。似乎(但我没有找到任何文件说明),ASP.NET Core MVC更喜欢注入的格式化程序而不是全局定义的格式化程序。

希望这能帮助其他人,因为我在这方面挣扎了很长时间...


2

为了能够在ASP .Net Core 3.1中使用@dcstraw的代码,我需要稍微修改MyModelBinder实现:

class MyModelBinder : IModelBinder
{
    private readonly BodyModelBinder _bodyModelBinder;

    public MyModelBinder(IHttpRequestStreamReaderFactory readerFactory, ILoggerFactory loggerFactory, IOptions<MvcOptions> options, IOptions<MvcNewtonsoftJsonOptions> jsonOptions, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider)
    {
        var formatters = options.Value.InputFormatters.ToList();
        int jsonFormatterIndex = formatters.FindIndex(formatter => formatter is NewtonsoftJsonInputFormatter);
        JsonSerializerSettings myCustomSettings = ...
        formatters[jsonFormatterIndex] = new NewtonsoftJsonInputFormatter(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);
    }
}

基本上:

  • JsonInputFormatter 变更为 NewtonsoftJsonInputFormatter
  • MvcJsonOptions 变更为 MvcNewtonsoftJsonOptions

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接