Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在使用ASP.NET Core 2.1的控制器上配置输入/输出格式化程序_C#_Asp.net Core - Fatal编程技术网

C# 在使用ASP.NET Core 2.1的控制器上配置输入/输出格式化程序

C# 在使用ASP.NET Core 2.1的控制器上配置输入/输出格式化程序,c#,asp.net-core,C#,Asp.net Core,我正在将一个旧的ASP.NET WebAPI 2.1项目重写为ASP.NET核心MVC 2.1。我面临的一个问题是如何移植服务的旧行为,该服务通过实现IControllerConfiguration接口的自定义属性配置输入和输出格式化程序。除了使用AddMvc(options)方法在全局级别注入格式化程序外,我找不到此接口的替代品,也找不到任何在控制器级别配置格式化程序的替代品。我没有找到任何可以在控制器级别配置的东西,但我确实找到了一个解决方案,其中包括对需要此功能的每个操作进行更改。在我的例

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

我没有找到任何可以在控制器级别配置的东西,但我确实找到了一个解决方案,其中包括对需要此功能的每个操作进行更改。在我的例子中,我需要自定义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);
    }
}
[HttpPost]
公共IActionResult Post([FromBodyCustomSerializationSettings]MyPostDto postDto)
{
...
}
类FromBodyCustomSerializationSettingsAttribute:ModelBinderAttribute
{
public FromBodyCustomSerializationSettingsAttribute():base(typeof(MyModelBinder))
{
BindingSource=BindingSource.Body;
}
}
类MyModelBinder:IModelBinder
{
专用只读BodyModelBinder\u BodyModelBinder;
公共MyModelBinder(IHttpRequestStreamReaderFactory readerFactory、ILoggerFactory loggerFactory、IOptions选项、IOptions jsonOptions、ArrayPool charPool、ObjectPoolProvider ObjectPoolProvider)
{
var formatters=options.Value.InputFormatters.ToList();
int jsonFormatterIndex=格式化程序.FirstIndexOf(格式化程序=>格式化程序是JsonInputFormatter);
JsonSerializerSettings myCustomSettings=。。。
格式化程序[jsonFormatterIndex]=新的JsonInputFormatter(loggerFactory.CreateLogger(“MyCustomJsonFormatter”)、myCustomSettings、charPool、objectPoolProvider、options.Value、jsonOptions.Value);
_bodyModelBinder=新的bodyModelBinder(格式化程序、readerFactory、loggerFactory、options.Value);
}
公共任务BindModelAsync(ModelBindingContext bindingContext)
{
返回_bodyModelBinder.bindmodelsync(bindingContext);
}
}

事实上我找到了一种方法。我创建了一个属性,该属性还实现了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);
  }
}
ResultExecuting上的公共void(ResultExecutingContext)
{
var objectResult=context.Result作为objectResult;
if(objectResult!=null)
{
var serializerSettings=new JsonSerializerSettings
{
ContractResolver=新的DefaultContractResolver()
};
var jsonFormatter=新的JsonOutputFormatter(
序列化设置,
ArrayPool.Shared);
objectResult.Formatters.Add(jsonFormatter);
}
}
基本上,在发送到客户机之前,我在每个对象结果中注入一个自定义JSON格式化程序。这样看来(但我没有找到任何相关文档),ASP.NET Core MVC更喜欢注入的格式化程序,而不是全局定义的格式化程序


我希望它能对其他人有所帮助,因为我在这方面一直在努力…

为了能够在ASP.Net Core 3.1中使用@dcstrow的代码,我需要稍微修改
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);
    }
}
类MyModelBinder:IModelBinder
{
专用只读BodyModelBinder\u BodyModelBinder;
公共MyModelBinder(IHttpRequestStreamReaderFactory readerFactory、ILoggerFactory loggerFactory、IOptions选项、IOptions jsonOptions、ArrayPool charPool、ObjectPoolProvider ObjectPoolProvider)
{
var formatters=options.Value.InputFormatters.ToList();
int jsonFormatterIndex=formatters.FindIndex(formatter=>formatter是NewtonsoftJsonInputFormatter);
JsonSerializerSettings myCustomSettings=。。。
格式化程序[jsonFormatterIndex]=新的NewtonsoftJsonInputFormatter(loggerFactory.CreateLogger(“MyCustomJsonFormatter”)、myCustomSettings、charPool、objectPoolProvider、options.Value、jsonOptions.Value);
_bodyModelBinder=新的bodyModelBinder(格式化程序、readerFactory、loggerFactory、options.Value);
}
公共任务BindModelAsync(ModelBindingContext bindingContext)
{
返回_bodyModelBinder.bindmodelsync(bindingContext);
}
}
基本上

  • JsonInputFormatter
    更改为
    NewtonsoftJsonInputFormatter
  • MvcJsonOptions
    更改为
    MvcNewtonsoftJsonOptions