首页 > 解决方案 > 在 ASP.NET Core 2.2 中将 `ProblemDetails` 与携带 `[Produces("application/xml")]` 的操作一起使用

问题描述

我打算使用ProblemDetails和继承类来表达 422 错误。

我在 ASP.NET Core 2.2 中创建了一个虚拟控制器类和一个操作:

[Route("api/v1")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet("values/json")]
    [Produces("application/json")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
    public ActionResult JsonGet()
    {
        var problemDetails = new ProblemDetails();
        return UnprocessableEntity(problemDetails);
    }

    [HttpGet("values/xml")]
    [Produces("application/xml")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
    public ActionResult XmlGet()
    {
        var problemDetails = new ProblemDetails();
        return UnprocessableEntity(problemDetails);
    }
}

但是当分别点击API时:

json 端点:

λ  Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/json" -Headers @{'Accept' = 'application/json'; }  
Invoke-WebRequest : The remote server returned an error: (422) Unprocessable Entity.                               
At line:1 char:1                                                                                                   
+ Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/json" -H ...                                        
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                            
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], W  
   ebException                                                                                                     
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand  

xml 端点:

λ  Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/xml" -Headers @{'Accept' = 'application/xml'; }
Invoke-WebRequest : The remote server returned an error: (406) Not Acceptable.
At line:1 char:1
+ Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/xml" -He ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], W
   ebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

标签: c#restasp.net-core

解决方案


我发现,这太愚蠢了……

事实证明,我认为 XML 支持是开箱即用的,但事实并非如此: https ://andrewlock.net/formatting-response-data-as-xml-or-json-based-on-the- url-in-asp-net-core/

我的Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new Info {Title = "C# Web API", Version = "v1"});
            var assemblyXmlPath = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, assemblyXmlPath);
            options.IncludeXmlComments(xmlPath);
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddXmlSerializerFormatters(); // <= this was missing...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseSwagger()
           .UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"));

        app.UseHttpsRedirection();
        app.UseMvc();
    }
}

现在,两个端点的一切都正常:

λ  Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/json" -Headers @{'Accept' = 'application/json'; }
Invoke-WebRequest : The remote server returned an error: (422) Unprocessable Entity.
At line:1 char:1
+ Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/json" -H ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], W
   ebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
λ  Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/xml" -Headers @{'Accept' = 'application/xml'; }
Invoke-WebRequest : The remote server returned an error: (422) Unprocessable Entity.
At line:1 char:1
+ Invoke-WebRequest -Uri "https://localhost:5001/api/v1/values/xml" -He ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], W
   ebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

我认为该错误有点误导或令人困惑,它使您认为问题来自控制器/操作配置而不是服务配置。


推荐阅读