- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个非常基本的项目,它只是抛出一个异常,期望得到一个 application/problem+json 响应,但我得到了一个包含错误详细信息的 html 页面。我猜这是我读过的一些帖子谈论的“开发人员异常页面”,但我没有将其添加到启动中。
完整代码示例:
using Microsoft.AspNetCore.Builder;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => {
throw new System.Exception("Hello, World!");
return new string[] { };
});
app.Run();
我在谷歌上找不到任何相关的内容,我认为这是因为它非常新鲜。
如果不在 Visual Studio 中运行,行为会改变吗?我可以更改它,以便在 Visual Studio 中运行时也获得 application/problem+json 吗?
最佳答案
在“开发”环境中运行时(即 IWebHostEnvironment.IsDevelopment()
为 true),开发人员异常页面现在默认打开(在 .NET 6 中)。
通常,在 ASP.NET Core 应用程序中配置异常处理时,在开发与生产(或更严格地说,非开发)期间将采用单独的路径进行异常处理。开发人员异常页面(顾名思义)仅用于开发,而异常处理程序中间件 (app.UseExceptionHandler
) 适用于非开发场景。
要返回异常的问题详细信息响应,您需要分别配置两个路径。开发人员异常页面有一个通过 IDeveloperPageExceptionFilter 接口(interface)的插件模型,可用于控制异常的呈现方式。 Here's an example当客户端指示它支持 JSON 时,过滤器将异常呈现为问题详细信息:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Diagnostics;
/// <summary>
/// Formats <see cref="DeveloperExceptionPageMiddleware"/> exceptions as JSON Problem Details if the client indicates it accepts JSON.
/// </summary>
public class ProblemDetailsDeveloperPageExceptionFilter : IDeveloperPageExceptionFilter
{
private static readonly object ErrorContextItemsKey = new object();
private static readonly MediaTypeHeaderValue _jsonMediaType = new MediaTypeHeaderValue("application/json");
private static readonly RequestDelegate _respondWithProblemDetails = RequestDelegateFactory.Create((HttpContext context) =>
{
if (context.Items.TryGetValue(ErrorContextItemsKey, out var errorContextItem) && errorContextItem is ErrorContext errorContext)
{
return new ErrorProblemDetailsResult(errorContext.Exception);
}
return null;
}).RequestDelegate;
public async Task HandleExceptionAsync(ErrorContext errorContext, Func<ErrorContext, Task> next)
{
var headers = errorContext.HttpContext.Request.GetTypedHeaders();
var acceptHeader = headers.Accept;
if (acceptHeader?.Any(h => h.IsSubsetOf(_jsonMediaType)) == true)
{
errorContext.HttpContext.Items.Add(ErrorContextItemsKey, errorContext);
await _respondWithProblemDetails(errorContext.HttpContext);
}
else
{
await next(errorContext);
}
}
}
internal class ErrorProblemDetailsResult : IResult
{
private readonly Exception _ex;
public ErrorProblemDetailsResult(Exception ex)
{
_ex = ex;
}
public async Task ExecuteAsync(HttpContext httpContext)
{
var problemDetails = new ProblemDetails
{
Title = $"An unhandled exception occurred while processing the request",
Detail = $"{_ex.GetType().Name}: {_ex.Message}",
Status = _ex switch
{
BadHttpRequestException ex => ex.StatusCode,
_ => StatusCodes.Status500InternalServerError
}
};
problemDetails.Extensions.Add("exception", _ex.GetType().FullName);
problemDetails.Extensions.Add("stack", _ex.StackTrace);
problemDetails.Extensions.Add("headers", httpContext.Request.Headers.ToDictionary(kvp => kvp.Key, kvp => (string)kvp.Value));
problemDetails.Extensions.Add("routeValues", httpContext.GetRouteData().Values);
problemDetails.Extensions.Add("query", httpContext.Request.Query);
var endpoint = httpContext.GetEndpoint();
if (endpoint != null)
{
var routeEndpoint = endpoint as RouteEndpoint;
var httpMethods = endpoint?.Metadata.GetMetadata<IHttpMethodMetadata>()?.HttpMethods;
problemDetails.Extensions.Add("endpoint", new {
endpoint?.DisplayName,
routePattern = routeEndpoint?.RoutePattern.RawText,
routeOrder = routeEndpoint?.Order,
httpMethods = httpMethods != null ? string.Join(", ", httpMethods) : ""
});
}
var result = Results.Json(problemDetails, statusCode: problemDetails.Status, contentType: "application/problem+json");
await result.ExecuteAsync(httpContext);
}
}
public static class ProblemDetailsDeveloperPageExtensions
{
/// <summary>
/// Adds a <see cref="IDeveloperPageExceptionFilter"/> that formats all exceptions as JSON Problem Details to clients
/// that indicate they support JSON via the Accepts header.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/></param>
/// <returns>The <see cref="IServiceCollection"/></returns>
public static IServiceCollection AddProblemDetailsDeveloperPageExceptionFilter(this IServiceCollection services) =>
services.AddSingleton<IDeveloperPageExceptionFilter, ProblemDetailsDeveloperPageExceptionFilter>();
}
你像这样在 DI 中注册它:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetailsDeveloperPageExceptionFilter();
var app = builder.Build();
对于非开发场景,您可以注册自己的端点来处理异常并在那里实现所需的行为,或者您可以使用像this one这样的中间件。 .
要自己执行此操作,您需要注册异常处理程序中间件并将其指向错误端点,该端点被写入以返回问题详细信息,like this :
...
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error");
}
var problemJsonMediaType = new MediaTypeHeaderValue("application/problem+json");
app.MapGet("/error", (HttpContext context) =>
{
var error = context.Features.Get<IExceptionHandlerFeature>()?.Error;
var badRequestEx = error as BadHttpRequestException;
var statusCode = badRequestEx?.StatusCode ?? StatusCodes.Status500InternalServerError;
if (context.Request.GetTypedHeaders().Accept?.Any(h => problemJsonMediaType.IsSubsetOf(h)) == true)
{
// JSON Problem Details
return error switch
{
BadHttpRequestException ex => Results.Extensions.Problem(detail: ex.Message, statusCode: ex.StatusCode),
_ => Results.Extensions.Problem()
};
}
// Plain text
context.Response.StatusCode = statusCode;
return Results.Text(badRequestEx?.Message ?? "An unhandled exception occurred while processing the request.");
})
.ExcludeFromDescription();
...
请注意,此示例中的某些部分使用 custom IResult
implementation目前,由于即将发布的 ASP.NET Core 6.0 rc.2 版本中正在修复一个问题
关于.net - application/problem+json 和 .net 6 最小 API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69351956/
我很绝望,现在已经两天(!!)天都没有解决方案来解决以下问题。 更新 Lion 后,我想使用最新版本的 rvm 安装额外的 rubies。 这是我之后调用 bundler 时发生的情况: /Users
我的问题: ajax 调用的无限循环会产生问题吗? 假设有这样的代码: ajaxcall(); function ajaxcall(){ jQuery.ajax({ typ
这是一个有趣的小项目,我已经开始尝试并最大限度地提高赢得办公室曲棍球池的机会。我试图找到最好的方法来选择 20 名能够在最高工资帽内给我最多分数的球员。 例如,假设原始数据由 玩家姓名 位置(前锋,后
我有一个总数为540000的数字列表。我想将此列表分为3个列表,每个列表总共180000。最有效的编程方法是这样做,假设数字列表是一个平面文件,每个数字为线? 最佳答案 听起来像Knapsack pr
抱歉,也许因为我不是英语,我不知道,但我找不到解决几个问题的任何资源;也许我用的词不正确.. 我想了解有关 iPhone 4 和 5 不同分辨率的更多信息。 首先:如果我开发针对 iPhone 4 分
在全局配置缓存后,如 docs ,如果我在 app.module 之外使用 CacheInterceptor,它会抛出错误。 app.module.ts const cacheConfig = {
我无法让 g:each 工作。我正在尝试遍历任何内容,但它永远不起作用 = 不生成任何 html。 索引.gsp Item ${i.name} 用户 Controller .g
在我的 XAML 文件中,我有一个这样声明的 ListBox:
想知道你是否可以帮助我: 我有一个名为initializeAll的方法: public final void initializeAll() { //other stuff........ rand
我尝试过使用 XML 和 JAVA 在我的 Android Activity 中创建一个 ImageView。这两次,我都能够获取我一天前创建的所有其他 PNG 资源以显示在 ImageView 中。
我需要你的帮助。这是什么意思? Warning: mysql_query() [function.mysql-query]: Access denied for user 'ODBC'
这是一段代码 function test() { this.value = "foo"; } $(document).ready(function () { test();
这是一些非常基础的东西。渲染期间引发异常:java.util.Locale.toLanguageTag()Ljava/lang/String; XML: 问题似乎出在 Edit
除其他来源外,我还使用 Stackoverflow 上的各种帖子,尝试实现我自己的 PHP 分类器,以将推文分类为正面、中性和负面类别。在编码之前,我需要弄清楚流程。我的思路和例子如下:
在过去的几周里,每当我在 Eclipse 上使用 SVN 插件时,我都会收到以下错误: Certificate Problem There is a problem with the site's s
我被拒绝运行以下功能(位于 /var/www/mysite/public_html/app/Controllers/Script.php) $structure = '/var/www/mysite/
我正在使用 ctags 为我的 Emacs 创建标签以使用 cygwin 从中读取符号。 Emacs 说 “访问标签表缓冲区:文件/home/superman/tags 不是有效的标签表” 这是我查找
我知道作为一种函数式语言,XSL 没有像传统的 for 循环(而是 for-each)那样的东西。 我正在尝试从可变数量的元素开始创建一个具有固定数量 (7) 的表。总之,我有
我正在使用RavenDB进行一些测试,以基于iphone应用程序存储数据。该应用程序将发送一个带有GPS key 的5个GPS坐标的字符串。我在RavenDB中看到每个文档约为664-668字节。这是
我无法理解我的应用程序的行为。我想创建一个简单的窗口 (1000x700px),分为两部分(分别为 250px 和 750px 宽度)。我尝试了以下代码: import java.awt.Color;
我是一名优秀的程序员,十分优秀!