我正在将旧的ASP.NET WebAPI 2.1项目重写为ASP.NET Core 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);
}
}
其实我找到了办法。我创建了一个也实现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更喜欢注入格式化程序而不是全局定义的格式化程序。
我希望它有助于其他因为我在努力...