Can I use MvcJsonOptions configured during Startup for serialization in custom middleware?

寵の児 提交于 2020-04-13 17:19:49

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!