问题
I am building an ASP.NET Core Api with a middleware for global exception handling. In Startup
class, I configured some JSON options which are to be used for all controllers.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});
}
Then, I created a custom middleware for exceptions handling. The middleware is supposed to log the error and return error response as JSON. The problem is that global Newtonsoft's JsonConvert
doesn't use the options which are specified during Mvc initialization (quite obvious).
Error handler middleware code:
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, ILogger<ErrorHandlingMiddleware> logger)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex, logger);
}
}
private Task HandleExceptionAsync(HttpContext context, Exception ex, ILogger logger)
{
var errorResponse = new ErrorResponse { Message = ex.Message };
logger.LogError(ex, errorResponse.Message);
var result = JsonConvert.SerializeObject(errorResponse);
context.Response.ContentType = "application/json";
context.Response.StatusCode = 500;
return context.Response.WriteAsync(result);
}
}
The question is: Is there any way to use the same JSON serializer, which is used in controllers, in my custom middleware? I would like to avoid setting up the same configuration in two separate places.
回答1:
JsonConvert.SerializeObject
has an overload that also takes an instance of JsonSerializerSettings, which could be combined with the options pattern and dependency injection. All-in-all, that would look something like this:
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly JsonSerializerSettings _jsonSerializerSettings;
public ErrorHandlingMiddleware(RequestDelegate next, IOptions<MvcJsonOptions> mvcJsonOptions)
{
_next = next;
_jsonSerializerSettings = mvcJsonOptions.Value.SerializerSettings;
}
...
private Task HandleExceptionAsync(HttpContext context, Exception ex, ILogger logger)
{
...
var result = JsonConvert.SerializeObject(errorResponse, _jsonSerializerSettings);
...
}
}
In this example, we're injecting the MvcJsonOptions
instance that's been configured and then passing its SerializerSettings
value through to JsonConvert.SerializeObject
.
来源:https://stackoverflow.com/questions/55305179/can-i-use-mvcjsonoptions-configured-during-startup-for-serialization-in-custom-m