C# 迁移到.Net Core 3.1时,.Net Core 2.2中使用的Services.AddMvc()和SuperJsonOutputFormatter的替代方案是什么

C# 迁移到.Net Core 3.1时,.Net Core 2.2中使用的Services.AddMvc()和SuperJsonOutputFormatter的替代方案是什么,c#,json.net,asp.net-core-webapi,.net-core-3.1,asp.net-apicontroller,C#,Json.net,Asp.net Core Webapi,.net Core 3.1,Asp.net Apicontroller,我正在迁移一个.Net Core 2.2 web API应用程序,该应用程序只有API控制器,没有视图。我在项目中使用SuperJsonOutputFormatter设置了自定义API响应。现在,我使用NewtonsoftJsonOutputFormatter为API创建自定义响应。但根据microsoft document services的说法,AddMvc()在.Net Core 3.1中已过时。那么,如何在startup.cs中调用customformatter。我正在使用下面的代码 s

我正在迁移一个.Net Core 2.2 web API应用程序,该应用程序只有API控制器,没有视图。我在项目中使用SuperJsonOutputFormatter设置了自定义API响应。现在,我使用NewtonsoftJsonOutputFormatter为API创建自定义响应。但根据microsoft document services的说法,AddMvc()在.Net Core 3.1中已过时。那么,如何在startup.cs中调用customformatter。我正在使用下面的代码

services.AddControllers().AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    options.SerializerSettings.Formatting = Formatting.Indented;
});
services.AddScoped<SuperJsonOutputFormatterFilter>();
services.AddMvc(opts =>
{
    opts.EnableEndpointRouting = false;
    var oldFormatter = opts.OutputFormatters.OfType<CustomOutputFormatter>().Single();
    opts.OutputFormatters.Remove(oldFormatter);
    var replacementJsonOutputFormatter =
       new CustomOutputFormatter(oldFormatter.serializerSettings, ArrayPool<char>.Shared);
    opts.OutputFormatters.Add(replacementJsonOutputFormatter);
}).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
上面的代码给出了一个运行时错误,即某些服务无法构造,验证服务描述符时出错。如何在不使用Services.AppMvc()的情况下调用customformatter

我的错误帮助程序如下所示

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   if (env.IsDevelopment())
   {
      app.UseDeveloperExceptionPage();
   }
   else
   {
      app.UseHsts();
   }
   app.UseRouting();
   app.UseExceptionHandler("/Error");
   app.UseAuthentication();
   app.UseStaticFiles();
   app.UseHttpsRedirection();
   app.UseMvc();
}
错误描述类

 public class ErrorDescription
    {
        public ErrorDescription(HttpStatusCode statusCode)
        {
            this.Code = (int)statusCode;
            this.Description = GetDescription((int)statusCode);
        }

        string GetDescription(int statusCode)
        {
            return statusCode switch
            {
                404 => "Employee ID not found",
                500 => "Internal server error",
                400 => "Device token already registered",
                406 => "No data found in table",
                _ => "",
            };
        }


        [JsonProperty("errorCode")]
        public int Code { get; set; }
        [JsonProperty("errorDescription")]
        public string Description { get; set; }
    }
FormatterFilter类

 public class CustomJsonOutputFormatterFilter : IAsyncActionFilter
    {
        private readonly CustomOutputFormatter _formatter;
        // inject SuperJsonOutputFormatter service
        public CustomJsonOutputFormatterFilter(CustomOutputFormatter formatter)
        {
            this._formatter = formatter;
        }
        // a helper method that provides an ObjectResult wrapper over the raw object
        private ObjectResult WrapObjectResult(ActionExecutedContext context, object obj)
        {
            var wrapper = new ObjectResult(obj);
            wrapper.Formatters.Add(this._formatter);
            context.Result = wrapper;
            return wrapper;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            ActionExecutedContext resultContext = await next();
            // in case we get a 500
            if (resultContext.Exception != null && !resultContext.ExceptionHandled)
            {
                var ewrapper = this.WrapObjectResult(resultContext, new { });
                ewrapper.StatusCode = (int)HttpStatusCode.InternalServerError;
                resultContext.ExceptionHandled = true;
                return;
            }
            else
            {
                switch (resultContext.Result)
                {
                    case BadRequestObjectResult b:      // 400 with an object
                        var bwrapper = this.WrapObjectResult(resultContext, b.Value);
                        bwrapper.StatusCode = b.StatusCode;
                        break;
                    case NotFoundObjectResult n:        // 404 with an object
                        var nwrapper = this.WrapObjectResult(resultContext, n.Value);
                        nwrapper.StatusCode = n.StatusCode;
                        break;
                    case ObjectResult o:                // plain object
                        this.WrapObjectResult(resultContext, o.Value);
                        break;
                    case JsonResult j:                  // plain json
                        this.WrapObjectResult(resultContext, j.Value);
                        break;
                    case StatusCodeResult s:             // other statusCodeResult(including NotFound,NoContent,...), you might want to custom this case 
                        var swrapper = this.WrapObjectResult(resultContext, new { result="" });
                        swrapper.StatusCode = s.StatusCode;
                        break;
                }
            }
        }

    }
自定义Outputformatter类,该类调用customformatterfilter

 public class CustomOutputFormatter : NewtonsoftJsonOutputFormatter
    {
        public CustomOutputFormatter(JsonSerializerSettings serializerSettings,
            ArrayPool<char> charPool) : base (serializerSettings, charPool)
        {
        }

        public JsonSerializerSettings serializerSettings { get; private set; }



        public override async Task WriteResponseBodyAsync(
            OutputFormatterWriteContext context,
            Encoding selectedEncoding)
        {

            if (context == null)
                throw new ArgumentNullException(nameof(context));
            if (selectedEncoding == null)
            if (selectedEncoding == null)
                throw new ArgumentNullException(nameof(selectedEncoding));
            using TextWriter writer = context.WriterFactory(context.HttpContext.Response.Body, selectedEncoding);
            var statusCode = context.HttpContext.Response.StatusCode;
            var rewrittenValue = new
            {
                status = IsSucceeded(statusCode),
                error = IsSucceeded(statusCode) ? null : new ErrorDescription((HttpStatusCode)statusCode),
                data = context.Object,
            };
            writer.Write(rewrittenValue);
            this.CreateJsonWriter(writer);
            await writer.FlushAsync();

        }

        private bool IsSucceeded(int statusCode)
        {
            // 204 is not an error but handled
            if (statusCode >= 400 || statusCode == 204) { return false; }
            return true;
        }
    }
公共类CustomOutputFormatter:NewtonsoftJsonOutputFormatter
{
公共CustomOutputFormatter(JsonSerializerSettings serializerSettings,
ArrayPool charPool):基本(serializerSettings,charPool)
{
}
公共JsonSerializerSettings serializerSettings{get;private set;}
公共重写异步任务WriteResponseBodyAsync(
OutputFormatterWriteContext,
编码选择(编码)
{
if(上下文==null)
抛出新ArgumentNullException(nameof(context));
如果(selectedEncoding==null)
如果(selectedEncoding==null)
抛出新ArgumentNullException(nameof(selectedEncoding));
使用TextWriter writer=context.WriterFactory(context.HttpContext.Response.Body,selectedEncoding);
var statusCode=context.HttpContext.Response.statusCode;
var重写值=新值
{
状态=Issucceed(状态代码),
错误=Issucceed(状态码)?空:新的错误描述((HttpStatusCode)状态码),
data=context.Object,
};
writer.Write(重写值);
this.CreateJsonWriter(writer);
等待writer.FlushAsync();
}
私有布尔值已被接受(int状态代码)
{
//204不是错误,但已处理
如果(statusCode>=400 | | statusCode==204){return false;}
返回true;
}
}

您可以使用Microsoft提供的迁移指南:


您可以使用Microsoft提供的迁移指南:


我没有详细介绍您的实现(它看起来很复杂,您想实现什么?),但是您可以使用
UseControllers()
,方法与之前使用
UseMvc()
配置
mvcopions
实例的方法相同。e、 g:

services.AddControllers(选项=>
{
Insert(0,新的VcardInputFormatter());
Insert(0,新VcardOutputFormatter());
})
这可能会解决您的问题-无需调用
AddMvc


但是,“某些服务无法构造”错误表明您缺少服务依赖项。错误消息将告诉您是哪一个。这是.NET Core 3.1中的一项新功能,即服务提供商验证,您可以使用。

我没有详细介绍您的实现(它似乎很复杂,您想实现什么?),但您可以使用
UseControllers()
与使用
UseMvc()的方式相同
之前配置
mvcopions
实例。e、 g:

services.AddControllers(选项=>
{
Insert(0,新的VcardInputFormatter());
Insert(0,新VcardOutputFormatter());
})
这可能会解决您的问题-无需调用
AddMvc


但是,“某些服务无法构造”错误表明您缺少服务依赖项。错误消息将告诉您是哪一个。这是.NET Core 3.1中的一项新功能,即服务提供商验证,您可以使用。

@kalitsov--您可以帮助我举一个示例,说明如何在不使用services.AddMvc()的情况下调用newtonsoftjsonoutputformatter。我的api中没有视图。它是一个只带有api控制器的web api应用程序我没有关于自定义响应实现的详细信息,但是
services.AddControllers().AddNewtonsoftJson()
必须足以更改隐式json格式化程序。也许你可以发布更完整的代码示例?@kalitsov-我已经编辑了我的问题。我已经提供了customformatter的详细信息。请建议如何在不使用services.AddMvc()@kalitsov的情况下使用.net core 3.1中的newtonsoft.json实现此功能--您能否帮助我举一个示例,说明如何在不使用services.AddMvc()的情况下调用newtonsoftjsonoutputformatter。我的api中没有视图。它是一个只带有api控制器的web api应用程序我没有关于自定义响应实现的详细信息,但是
services.AddControllers().AddNewtonsoftJson()
必须足以更改隐式json格式化程序。也许你可以发布更完整的代码示例?@kalitsov-我已经编辑了我的问题。我已经提供了customformatter的详细信息。请建议如何在不使用services.AddMvc()的情况下使用.net core 3.1中的newtonsoft.json实现此功能