【问题标题】:Configure input/output formatters on controllers with ASP.NET Core 2.1使用 ASP.NET Core 2.1 在控制器上配置输入/输出格式化程序
【发布时间】:2018-08-09 14:18:04
【问题描述】:

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

【问题讨论】:

    标签: c# asp.net-core


    【解决方案1】:

    我还没有找到可以在控制器级别配置的任何内容,但我确实找到了一个解决方案,该解决方案涉及对您需要此功能的每个操作进行更改。在我的情况下,我需要自定义 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);
        }
    }
    

    【讨论】:

      【解决方案2】:

      其实我找到了办法。我创建了一个也实现 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 以这种方式更喜欢注入的格式化程序而不是全局定义的格式化程序。

      我希望它对其他人有所帮助,因为我一直在努力解决这个问题......

      【讨论】:

        【解决方案3】:

        为了能够在 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-01
          • 2017-09-11
          • 1970-01-01
          • 2023-03-27
          • 2020-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多