问题
I am trying to change the JSON parser in my web API project.
I have followed the following tutorials:
https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-2.2
https://www.youtube.com/watch?v=tNzgXjqqIjI
https://weblog.west-wind.com/posts/2012/Mar/09/Using-an-alternate-JSON-Serializer-in-ASPNET-Web-API
I now have the following code:
public class MyJsonFormatter : MediaTypeFormatter
{
public MyJsonFormatter()
{
base.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
{
return null;
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
return null;
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
}
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
return base.GetPerRequestFormatterInstance(type, request, mediaType);
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
return null;
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
{
return null;
}
public override IRequiredMemberSelector RequiredMemberSelector { get => base.RequiredMemberSelector; set => base.RequiredMemberSelector = value; }
}
public static void Register(HttpConfiguration config)
{
///Other stuff...
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Insert(0, new MyJsonFormatter());
}
My issue is that whatever I do, JSON gets parsed and it seems to ignore my code - I can throw exceptions in the read or write methods and nothing will happen, break points do not get hit etc.
I know this formatter is being added as only the content types in my class are visible and if I set CanReadType
to return false then nothing gets parsed.
My question is, how can I make the code execute my overrides?
回答1:
Update how the formatter is registered
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Other stuff...
var jsonFormatter = new MyJsonFormatter();
config.Formatters.Clear();
config.Formatters.Insert(0, jsonFormatter);
//...
}
}
Making sure the suggested syntax is followed in Startup or where ever the application is started.
// configure Web Api
GlobalConfiguration.Configure(WebApiConfig.Register);
There is also the process of content negotiation as suggested in the following article
Supporting only JSON in ASP.NET Web API – the right way
Adapting it to your example, it would look like
public class JsonContentNegotiator : IContentNegotiator {
MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
private readonly MyJsonFormatter _jsonFormatter;
public JsonContentNegotiator(MyJsonFormatter formatter) {
_jsonFormatter = formatter;
}
public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters) {
var result = new ContentNegotiationResult(_jsonFormatter, mediaType);
return result;
}
}
And registered against your HttpConfiguration
var jsonFormatter = new MyJsonFormatter();
config.Formatters.Clear();
config.Formatters.Insert(0, jsonFormatter);
//update content negotiation
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
Finally one piece of information to note is that the framework did tightly couple its JSON formatting to its own JsonMediaTypeFormatter
/// <summary>
/// Gets the <see cref="MediaTypeFormatter"/> to use for Json.
/// </summary>
public JsonMediaTypeFormatter JsonFormatter
{
get { return Items.OfType<JsonMediaTypeFormatter>().FirstOrDefault(); }
}
Reference source
So depending on how much of the pipeline actually depends on the existence of an instance of JsonMediaTypeFormatter
, it would probably affect JSON related formatting.
If it is in fact a problem then my suggestion would be to derive from JsonMediaTypeFormatter
and override its members as needed.
public class MyJsonFormatter : JsonMediaTypeFormatter {
//... removed for brevity
}
But that might bring with it, its own problems depending on what that base class is coupled to.
回答2:
You need to register your formatter in the startup config.
来源:https://stackoverflow.com/questions/54203063/web-api-change-json-parser