这个问题几乎是逐字逐句this stackoverflow question
但是我想在ASP.NET Core Api中完成它。我打算将它实现为头而不是查询字符串。我正在努力改变在ConfigureServices方法中设置的Json SerializerSettings。
services.AddMvc(config =>
{
config.Filters.Add(new WebApiRequireHttps());
})
.AddJsonOptions(options =>
{
options.SerializerSettings.Formatting = Formatting.Indented;
});
我想要完成的是在我设置像X-MyApi-Pretty:false这样的标题时,将Serializer的设置更改为使用Formatting.None。
我正在尝试像上述问题一样创建自己的ActionFIlterAttribute。 Microsoft.AspNetCore.Mvc.Filters使用ActionExecutedContext,它似乎与ActionContext.RequestContext.Configuration.Formatters.JsonFormatter没有明显的等价。
是否存在相应的问题,或者我只是认为这一切都错了? 我的google-fu真的让我失望了,我觉得我错过了一些非常明显的东西。
答案 0 :(得分:4)
如果您希望它是全局的,您可以注册自定义输出格式化程序。这是我制作的一个实例。你可以自由使用。
它的工作原理是读取一个名为“jsonformat”的标题,用于命名的json序列化器设置,例如名为“pretty”的设置。如果没有标头,或标头无效,则它将回退到默认的json序列化器设置。如果您希望全局可用,则这可能是一种更简洁的方法 - 无需操作过滤器。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
...
public class NamedFormatJsonOutputFormatter : JsonOutputFormatter
{
private readonly IDictionary<string, JsonSerializerSettings> _customJsonSettings;
private readonly IDictionary<string, JsonSerializer> _customSerializers;
public NamedFormatJsonOutputFormatter(JsonSerializerSettings defaultSerializerSettings, IDictionary<string, JsonSerializerSettings> customJsonSettings, ArrayPool<char> charPool) : base (defaultSerializerSettings, charPool)
{
_customJsonSettings = customJsonSettings;
_customSerializers = new Dictionary<string, JsonSerializer>();
}
protected virtual JsonSerializer CreateCustomJsonSerializer(string serializerName)
{
JsonSerializer outputSerializer;
var exists = _customSerializers.TryGetValue(serializerName, out outputSerializer);
if (!exists)
{
var settings = _customJsonSettings[serializerName];
outputSerializer = JsonSerializer.Create(settings);
_customSerializers[serializerName] = outputSerializer;
}
return _customSerializers[serializerName];
}
public void WriteObjectWithNamedSerializer(TextWriter writer, string serializerName, object value)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
using (var jsonWriter = CreateJsonWriter(writer))
{
var jsonSerializer = CreateCustomJsonSerializer(serializerName);
jsonSerializer.Serialize(jsonWriter, value);
}
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
var jsonSerializerNameHeader = context.HttpContext.Request.Headers.FirstOrDefault(h => h.Key == "jsonformat" && h.Value.Intersect(_customJsonSettings.Keys).Any());
if (jsonSerializerNameHeader.Equals(default(KeyValuePair<string, StringValues>)))
{
await base.WriteResponseBodyAsync(context, selectedEncoding);
return;
}
var jsonFormatName = jsonSerializerNameHeader.Value.FirstOrDefault();
var response = context.HttpContext.Response;
using (var writer = context.WriterFactory(response.Body, selectedEncoding))
{
WriteObjectWithNamedSerializer(writer, jsonFormatName, context.Object);
await writer.FlushAsync();
}
}
}
然后在您的services.AddMvc
中注册using System.Buffers;
using Microsoft.AspNetCore.Mvc.Formatters;
...
services.AddMvc(options =>
{
options.OutputFormatters.RemoveType<JsonOutputFormatter>();
options.OutputFormatters.Add(new NamedFormatJsonOutputFormatter(new JsonSerializerSettings(),
new Dictionary<string, JsonSerializerSettings>()
{
{
"pretty", new JsonSerializerSettings()
{
Formatting = Formatting.Indented
}
}
}, ArrayPool<char>.Shared));
});