ASP.NET Core 8.0의 새로운 기능

이 문서에서는 ASP.NET Core 8.0의 가장 중요한 변경 내용과 관련 설명서에 대한 링크를 강조 표시합니다.

Blazor

전체 스택 웹 UI

.NET 8 Blazor 릴리스에서는 다음을 사용하여 구성 요소 또는 페이지 수준에서 콘텐츠를 렌더링하는 앱을 개발하기 위한 전체 스택 웹 UI 프레임워크입니다.

  • 정적 서버 렌더링(정적 서버 쪽 렌더링, 정적 SSR이라고도 함)을 사용하여 서버에 정적 HTML을 생성합니다.
  • 대화형 서버 렌더링(대화형 서버 쪽 렌더링, 대화형 SSR이라고도 함)을 사용하여 서버에서 미리 렌더링된 대화형 구성 요소를 생성합니다.
  • 대화형 WebAssembly 렌더링(항상 대화형으로 간주되는 클라이언트 쪽 렌더링이라고도 함) 서버에서 미리 렌더링된 대화형 구성 요소를 클라이언트에 생성합니다.
  • 대화형 자동(자동) 렌더링은 처음에 콘텐츠 렌더링 및 대화형 작업에 서버 쪽 ASP.NET Core 런타임을 사용합니다. 클라이언트의 .NET WebAssembly 런타임은 번들이 다운로드되고 WebAssembly 런타임이 활성화된 후 Blazor 후속 렌더링 및 대화형 작업에 사용됩니다. 대화형 자동 렌더링은 일반적으로 가장 빠른 앱 시작 환경을 제공합니다.

대화형 렌더링 모드는 기본적으로 콘텐츠를 미리 렌더링합니다.

자세한 내용은 다음 문서를 참조하세요.

설명서 전체의 Blazor 예제가 Web Apps에서 Blazor 사용하도록 업데이트되었습니다. Blazor Server예는 .NET 7 이하 버전이 지정된 콘텐츠에서 다시 기본.

정적 서버 쪽 렌더링을 사용하는 클래스 라이브러리에 대한 새 문서(정적 SSR)

정적 서버 쪽 렌더링(정적 SSR)을 사용하여 클래스 라이브러리(RCL)의 구성 요소 라이브러리 작성 Razor 에 대해 설명하는 새 문서를 추가했습니다.

자세한 내용은 정적 서버 쪽 렌더링(정적 SSR)이 있는 ASP.NET Core Razor 클래스 라이브러리(RCL)를 참조하세요.

HTTP 캐싱 문제에 대한 새 문서

주요 버전에서 앱을 업그레이드 Blazor 할 때 발생할 수 있는 몇 가지 일반적인 HTTP 캐싱 문제와 HTTP 캐싱 문제를 해결하는 방법을 설명하는 새 문서를 추가했습니다.

자세한 내용은 ASP.NET Core Blazor 앱을 업그레이드할 때 HTTP 캐싱 문제 방지를 참조하세요.

새 Blazor 웹앱 템플릿

새 Blazor 프로젝트 템플릿인 웹앱 템플릿을 Blazor 도입했습니다. 새 템플릿은 구성 요소를 사용하여 Blazor 모든 스타일의 웹 UI를 빌드하기 위한 단일 시작점을 제공합니다. 템플릿은 기존 Blazor Server 및 호스팅 모델의 강점을 Blazor WebAssembly .NET 8에 추가된 새로운 Blazor 기능인 정적 SSR(서버 쪽 렌더링), 스트리밍 렌더링, 향상된 탐색 및 양식 처리 및 구성 요소별로 사용 Blazor Server 하거나 Blazor WebAssembly 구성 요소별로 상호 작용을 추가하는 기능을 결합합니다.

다양한 Blazor 호스팅 모델을 .NET 8의 단일 모델로 통합하는 과정의 일환으로 프로젝트 템플릿의 Blazor 수도 통합하고 있습니다. 템플릿을 Blazor Server 제거했고 ASP.NET Core Hosted 옵션이 템플릿에서 Blazor WebAssembly 제거되었습니다. 이러한 두 시나리오는 모두 웹앱 템플릿을 사용할 때 옵션으로 Blazor 표시됩니다.

참고 항목

기존 Blazor Server 및 Blazor WebAssembly 앱은 .NET 8에서 기본 지원됩니다. 필요에 따라 새 전체 스택 웹 UI Blazor 기능을 사용하도록 이러한 앱을 업데이트할 수 있습니다.

새 Blazor 웹앱 템플릿에 대한 자세한 내용은 다음 문서를 참조하세요.

Web Apps의 Blazor 새 JS 이니셜라이저

, Blazor WebAssembly및 Blazor Hybrid 앱의 경우Blazor Server:

  • beforeStart 는 로드 프로세스 사용자 지정, 로깅 수준 및 기타 옵션과 같은 작업에 사용됩니다.
  • afterStarted 는 이벤트 수신기 및 사용자 지정 이벤트 유형 등록 Blazor 과 같은 작업에 사용됩니다.

이전 레거시 JS 이니셜라이저는 웹앱에서 Blazor 기본적으로 호출되지 않습니다. Web Apps의 경우 새 이니셜라이저 집합이 afterWebStartedbeforeWebAssemblyStartafterServerStartedbeforeServerStartafterWebAssemblyStarted사용됩니다. beforeWebStartJSBlazor

자세한 내용은 ASP.NET Core Blazor 시작을 참조하세요.

미리 렌더링 및 통합 지침 분할

.NET의 이전 릴리스에서는 단일 문서에서 미리 렌더링 및 통합을 다루었습니다. 범위를 단순화하고 집중하기 위해 .NET 8용으로 업데이트된 다음 새 문서로 주제를 분할했습니다.

웹앱에서 Blazor 구성 요소 상태 유지

기존 PersistentComponentState 서비스를 사용하여 웹앱에서 Blazor 구성 요소 상태를 유지 및 읽을 수 있습니다. 이는 미리 렌더링하는 동안 구성 요소 상태를 유지하는 데 유용합니다.

BlazorWeb Apps는 미리 렌더링하는 동안 생성된 등록된 앱 수준 상태를 자동으로 유지하므로 구성 요소 상태 유지 태그 도우미필요하지 않습니다.

양식 처리 및 모델 바인딩

Blazor 이제 구성 요소는 모델 바인딩 및 요청 데이터 유효성 검사를 포함하여 제출된 양식 요청을 처리할 수 있습니다. 구성 요소는 표준 HTML <form> 태그를 사용하거나 기존 구성 요소를 사용하여 별도의 양식 처리기를 사용하여 양식을 구현할 EditForm 수 있습니다.

양식 모델 바인딩은 Blazor 양식 데이터가 모델에 바인딩되는 방식을 사용자 지정하기 위한 데이터 계약 특성(예 [DataMember] : 및 [IgnoreDataMember])을 적용합니다.

새 위조 방지 지원이 .NET 8에 포함되어 있습니다. 새 AntiforgeryToken 구성 요소는 위조 방지 토큰을 숨겨진 필드로 렌더링하고 새 [RequireAntiforgeryToken] 특성은 위조 방지 보호를 사용하도록 설정합니다. 위조 방지 검사 실패하면 양식 처리 없이 400(잘못된 요청) 응답이 반환됩니다. 새 위조 방지 기능은 기본적으로 양식에 대해 사용하도록 설정되며 표준 HTML 양식에 Editform 수동으로 적용할 수 있습니다.

자세한 내용은 ASP.NET Core Blazor 양식 개요를 참조하세요.

향상된 탐색 및 양식 처리

정적 서버 쪽 렌더링(정적 SSR)은 일반적으로 사용자가 새 페이지로 이동하거나 양식을 제출할 때마다 전체 페이지 새로 고침을 수행합니다. .NET 8 Blazor 에서는 요청을 가로채고 대신 페치 요청을 수행하여 페이지 탐색 및 양식 처리를 향상시킬 수 있습니다. Blazor 그런 다음, 렌더링된 응답 콘텐츠를 브라우저 DOM에 패치하여 처리합니다. 향상된 탐색 및 양식 처리를 사용하면 전체 페이지 새로 고침이 필요하지 않으며 페이지 상태가 더 많이 유지되므로 페이지가 더 빠르고 원활하게 로드됩니다. 향상된 탐색은 스크립트(blazor.web.js)가 로드될 때 Blazor 기본적으로 사용하도록 설정됩니다. 특정 양식에 대해 향상된 양식 처리를 선택적으로 사용하도록 설정할 수 있습니다.

향상된 새로운 탐색 API를 사용하면 호출 NavigationManager.Refresh(bool forceLoad = false)하여 현재 페이지를 새로 고칠 수 있습니다.

자세한 내용은 라우팅 문서의 다음 섹션을 Blazor 참조하세요.

interop에 대한 향상된 탐색을 사용하는 정적 렌더링에 대한 JS 새 문서

일부 앱은 각 페이지와 JS 관련된 초기화 작업을 수행하기 위해 interop에 의존합니다. interop 초기화 작업을 수행하는 JS 정적으로 렌더링된 페이지와 함께 향상된 탐색 기능을 사용하는 Blazor경우 향상된 페이지 탐색이 발생할 때마다 페이지별 JS 페이지가 예상대로 다시 실행되지 않을 수 있습니다. 새 문서에서는 Web Apps에서 이 시나리오를 Blazor 해결하는 방법을 설명합니다.

정적 서버 쪽 렌더링을 사용하여 Core Blazor JavaScript ASP.NET(정적 SSR)

스트리밍 렌더링

이제 정적 서버 쪽 렌더링(정적 SSR)을 사용할 때 응답 스트림에서 콘텐츠 업데이트를 스트리밍할 수 있습니다 Blazor. 스트리밍 렌더링은 사용 가능한 한 빨리 콘텐츠를 렌더링하여 완전히 렌더링하기 위해 장기 실행 비동기 작업을 수행하는 페이지의 사용자 환경을 향상시킬 수 있습니다.

예를 들어 페이지를 렌더링하려면 장기 실행 데이터베이스 쿼리 또는 API 호출을 수행해야 할 수 있습니다. 일반적으로 렌더링된 응답을 보내기 전에 페이지 렌더링의 일부로 실행되는 비동기 작업이 완료되어야 하므로 페이지 로드가 지연될 수 있습니다. 스트리밍 렌더링은 비동기 작업이 실행되는 동안 처음에 전체 페이지를 자리 표시자 콘텐츠로 렌더링합니다. 비동기 작업이 완료되면 업데이트된 콘텐츠가 동일한 응답 연결에서 클라이언트로 전송되고 DOM에 의해 패치됩니다. 이 방법의 이점은 앱의 기본 레이아웃이 최대한 빨리 렌더링되고 콘텐츠가 준비되는 즉시 페이지가 업데이트된다는 것입니다.

자세한 내용은 ASP.NET Core Razor 구성 요소 렌더링을 참조하세요.

구성 요소에 키 입력 서비스 삽입

Blazor 이제 특성을 사용하여 키 지정된 서비스 삽입을 [Inject] 지원합니다. 키는 종속성 주입을 사용할 때 등록 및 서비스 사용 범위를 허용합니다. 새 InjectAttribute.Key 속성을 사용하여 삽입할 서비스에 대한 키를 지정합니다.

[Inject(Key = "my-service")]
public IMyService MyService { get; set; }

이 지시문은 @injectRazor 이 릴리스에 대한 키 서비스를 지원하지 않지만 향후 .NET 릴리스에 대해 키 지정된 서비스(dotnet/razor #9286)를 지원하기 위해 업데이트 @inject 에서 작업을 추적합니다.

자세한 내용은 ASP.NET Core Blazor 종속성 주입을 참조하세요.

연계 매개 변수로 액세스 HttpContext

이제 정적 서버 구성 요소에서 연계 매개 변수로 현재 HttpContext 에 액세스할 수 있습니다.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

정적 서버 구성 요소에서 액세스하는 HttpContext 것은 헤더 또는 기타 속성을 검사하고 수정하는 데 유용할 수 있습니다.

상태, 액세스 및 새로 고침 토큰을 HttpContext 구성 요소에 전달하는 예제는 서버 쪽 ASP.NET Core Blazor 추가 보안 시나리오를 참조하세요.

ASP.NET Core 외부에서 구성 요소 렌더링 Razor

이제 HTTP 요청의 컨텍스트 외부에서 구성 요소를 렌더링 Razor 할 수 있습니다. 구성 요소를 HTML로 직접 문자열에 렌더링 Razor 하거나 ASP.NET Core 호스팅 환경과 독립적으로 스트림할 수 있습니다. 이는 전자 메일 또는 정적 사이트 콘텐츠 생성과 같은 HTML 조각을 생성하려는 시나리오에 편리합니다.

자세한 내용은 ASP.NET Core 외부에서 구성 요소 렌더링 Razor 을 참조하세요.

섹션 지원

SectionOutlet 구성 요소와 SectionContent 구성 요소는 Blazor 나중에 채울 수 있는 콘텐츠에 대한 콘센트를 지정하는 지원을 추가합니다. 섹션은 레이아웃에서 자리 표시자를 정의한 다음 특정 페이지로 채워지는 데 자주 사용됩니다. 섹션은 고유한 이름 또는 고유한 개체 ID를 사용하여 참조됩니다.

자세한 내용은 ASP.NET Core Blazor 섹션을 참조하세요.

오류 페이지 지원

BlazorWeb Apps는 ASP.NET Core 예외 처리 미들웨어와 함께 사용할 사용자 지정 오류 페이지를 정의할 수 있습니다. 웹앱 프로젝트 템플릿에는 Blazor MVC 및 Razor Pages 앱에서 사용되는 것과 유사한 콘텐츠가 있는 기본 오류 페이지(Components/Pages/Error.razor)가 포함되어 있습니다. 예외 처리 미들웨어의 요청에 대한 응답으로 오류 페이지가 렌더링되면 대화형 작업이 활성화되어 있더라도 오류 페이지는 항상 정적 서버 구성 요소로 렌더링됩니다.

Error.razor 8.0 참조 원본

QuickGrid

Blazor QuickGrid 구성 요소는 더 이상 실험적이 아니고 이제 .NET 8의 프레임워크에 Blazor 속합니다.

QuickGrid는 테이블 형식으로 데이터를 표시하기 위한 고성능 그리드 구성 요소입니다. QuickGrid는 정렬, 필터링, 페이징 및 가상화와 같은 강력한 기능을 제공하면서 데이터를 표시하는 간단하고 편리한 방법으로 빌드되었습니다.

자세한 내용은 ASP.NET Core Blazor QuickGrid 구성 요소를 참조하세요.

명명된 요소로 라우팅

Blazor 이제 클라이언트 쪽 라우팅을 사용하여 표준 URL 조각을 사용하여 페이지의 특정 HTML 요소로 이동할 수 있습니다. 표준 id 특성을 Blazor 사용하여 HTML 요소의 식별자를 지정하는 경우 URL 조각이 요소 식별자와 일치할 때 해당 요소로 올바르게 스크롤됩니다.

자세한 내용은 ASP.NET Core Blazor 라우팅 및 탐색을 참조하세요.

루트 수준 연계 값

루트 수준 연계 값은 전체 구성 요소 계층 구조에 대해 등록할 수 있습니다. 업데이트 알림에 대한 명명된 연계 값 및 구독이 지원됩니다.

자세한 내용은 ASP.NET Core Blazor 연계 값 및 매개 변수를 참조하세요.

빈 콘텐츠 가상화

구성 요소가 로드되고 비어 있거나 ItemsItemsProviderResult<T>.TotalItemCount 0일 때 구성 요소의 새 EmptyContent 매개 변수 Virtualize 를 사용하여 콘텐츠를 제공합니다.

자세한 내용은 ASP.NET Core Razor 구성 요소 유효성 검사를 참조하세요.

대화형 서버 구성 요소를 다시 기본 없는 경우 회로 닫기

대화형 서버 구성 요소는 회로라는 브라우저와 실시간 연결을 사용하여 웹 UI 이벤트를 처리합니다. 루트 대화형 서버 구성 요소가 렌더링될 때 회로 및 연결된 상태가 설정됩니다. 페이지에 다시 기본 대화형 서버 구성 요소가 없으면 회로가 닫혀 서버 리소스를 확보합니다.

회로 활동 모니터링 SignalR

이제 새 CreateInboundActivityHandler 메서드를 사용하여 서버 쪽 앱에서 인바운드 회로 작업을 모니터링할 수 있습니다 CircuitHandler. 인바운드 회로 활동은 UI 이벤트 또는 JavaScript-to-.NET interop 호출과 같이 브라우저에서 서버로 전송되는 모든 활동입니다.

자세한 내용은 ASP.NET Core BlazorSignalR 지침을 참조하세요.

Jiterpreter를 사용하여 더 빠른 런타임 성능

Jiterpreter는 .NET 8의 새로운 런타임 기능으로, WebAssembly에서 실행할 때 JIT(Just-In-Time) 컴파일을 부분적으로 지원하여 런타임 성능을 향상시킬 수 있습니다.

자세한 내용은 ASP.NET Core Blazor WebAssembly 호스트 및 배포를 참조하세요.

AOT(Ahead-Of-Time) SIMD 및 예외 처리

Blazor WebAssemblyAOT(Ahead-Of-Time) 컴파일은 이제 기본적으로 WebAssembly 고정 너비 SIMDWebAssembly 예외 처리를 사용하여 런타임 성능을 향상시킵니다.

자세한 내용은 다음 문서를 참조하세요.

웹 친화적인 웹빌 패키징

웹빌은 파일 다운로드 또는 사용을 차단하는 환경에 배포할 때 발생하는 문제를 방지하기 위해 네이티브 Windows 실행과 관련된 콘텐츠를 제거하는 .NET 어셈블리의 .dll 웹 친화적 패키징입니다. 웹빌은 기본적으로 앱에 사용하도록 Blazor WebAssembly 설정됩니다.

자세한 내용은 ASP.NET Core Blazor WebAssembly 호스트 및 배포를 참조하세요.

참고 항목

.NET 8이 릴리스되기 전에 ASP.NET Core 호스팅 Blazor WebAssembly 앱에 대한 배포 레이아웃 지침은 클라이언트가 다중 파트 번들 접근 방식으로 DLL을 다운로드하고 실행하는 것을 차단하는 환경을 다룹니다. .NET 8 이상 Blazor 에서는 웹실 파일 형식을 사용하여 이 문제를 해결합니다. WebAssembly 배포 레이아웃 문서에서 설명하는 실험적 NuGet 패키지를 사용하는 다중 파트 번들링은 .NET 8 이상의 앱에서 지원 Blazor 되지 않습니다. 자세한 내용은 사용자 지정 번들 형식(dotnet/aspnetcore #36978)을 정의하려면 패키지 향상 Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle 을 참조하세요. .NET 8 이상 앱에서 다중 파트 번들 패키지를 계속 사용하려는 경우 문서의 지침을 사용하여 고유한 다중 파트 번들 NuGet 패키지를 만들 수 있지만 Microsoft에서는 지원하지 않습니다.

Blazor WebAssembly 디버깅 기능 개선

WebAssembly에서 .NET을 디버깅할 때 디버거는 이제 Visual Studio 기본 설정에 구성된 기호 위치에서 기호 데이터를 다운로드합니다. 이렇게 하면 NuGet 패키지를 사용하는 앱의 디버깅 환경이 향상됩니다.

이제 Firefox를 사용하여 앱을 디버그 Blazor WebAssembly 할 수 있습니다. 앱을 디버깅 Blazor WebAssembly 하려면 원격 디버깅을 위해 브라우저를 구성한 다음 .NET WebAssembly 디버깅 프록시를 통해 브라우저 개발자 도구를 사용하여 브라우저에 연결해야 합니다. 현재 Visual Studio에서 Firefox 디버깅은 지원되지 않습니다.

자세한 내용은 ASP.NET Core Blazor 앱 디버그를 참조하세요.

CSP(콘텐츠 보안 정책) 호환성

Blazor WebAssembly CSP(콘텐츠 보안 정책)를 unsafe-eval 지정할 때 더 이상 스크립트 원본을 사용하도록 설정할 필요가 없습니다.

자세한 내용은 ASP.NET Core에 대한 콘텐츠 보안 정책 적용을 참조 하세요 Blazor.

구성 요소의 수명 주기 외부에서 catch된 Razor 예외 처리

구성 요소에서 Razor 구성 요소의 수명 주기 호출 스택 외부에서 throw된 예외를 처리하는 데 사용합니다ComponentBase.DispatchExceptionAsync. 이렇게 하면 구성 요소의 코드가 수명 주기 메서드 예외인 것처럼 예외를 처리할 수 있습니다. 그 후 오류 Blazor경계와 같은 오류 처리 메커니즘은 예외를 처리할 수 있습니다.

자세한 내용은 ASP.NET Core Blazor 앱의 오류 처리를 참조하세요.

.NET WebAssembly 런타임 구성

이제 .NET WebAssembly 런타임을 시작하도록 Blazor 구성할 수 있습니다.

자세한 내용은 ASP.NET Core Blazor 시작을 참조하세요.

에서 연결 시간 제한 구성 HubConnectionBuilder

허브 연결 시간 제한을 구성하기 위한 이전 해결 방법은 공식 SignalR 허브 연결 작성기 시간 제한 구성으로 바꿀 수 있습니다.

자세한 내용은

프로젝트 템플릿은 오픈 아이코닉을 흘렸습니다.

프로젝트 템플릿은 Blazor 더 이상 아이콘에 대해 아이콘 열기의존하지 않습니다.

대화 상자 취소 및 이벤트 닫기 지원

Blazor 이제 HTML 요소의 cancel 이벤트 및 close 해당 이벤트를 dialog 지원합니다.

다음 예제에서

  • OnClose는 닫기 단추로 대화 상자를 닫my-dialog 호출됩니다.
  • OnCancel는 Esc 키를 사용하여 대화 상자를 취소할 때 호출됩니다. Esc 키를 사용하여 HTML 대화 상자를 해제하면 이벤트와 close 이벤트가 모두 cancel 트리거됩니다.
<div>
    <p>Output: @message</p>

    <button onclick="document.getElementById('my-dialog').showModal()">
        Show modal dialog
    </button>

    <dialog id="my-dialog" @onclose="OnClose" @oncancel="OnCancel">
        <p>Hi there!</p>

        <form method="dialog">
            <button>Close</button>
        </form>
    </dialog>
</div>

@code {
    private string? message;

    private void OnClose(EventArgs e) => message += "onclose, ";

    private void OnCancel(EventArgs e) => message += "oncancel, ";
}

BlazorIdentity Ui

Blazor 는 개별 계정에 대한 인증 옵션을 선택할 때 전체 Blazor기반 Identity UI 생성을 지원합니다. Visual Studio에서 Web Apps에 대한 새 프로젝트 대화 상자에서 개별 계정에 대한 Blazor 옵션을 선택하거나 새 프로젝트를 만들 때 명령줄에서 설정된 Individual 옵션을 전달할 -au|--auth 수 있습니다.

자세한 내용은 다음 리소스를 참조하세요.

ASP.NET Core로 보안 Blazor WebAssemblyIdentity

이 Blazor 설명서는 ASP.NET CoreIdentity를 사용하여 독립 실행형 Blazor WebAssembly 앱 보안을 다루는 새 문서 및 샘플 앱을 호스팅합니다.

자세한 내용은 다음 리소스를 참조하세요.

Blazor Server Yarp 라우팅

Yarp에 대한 Blazor Server 라우팅 및 딥 링크는 .NET 8에서 올바르게 작동합니다.

자세한 내용은 ASP.NET Core 7.0에서 8.0으로 마이그레이션을 참조하세요.

Blazor Hybrid

다음 문서에서는 .NET 8의 변경 내용을 Blazor Hybrid 설명합니다.

  • ASP.NET Core Blazor Hybrid문제 해결: 새 문서에서는 로깅을 사용하는 BlazorWebView 방법을 설명합니다.
  • .NET MAUIBlazor Hybrid 앱 빌드: 프로젝트 템플릿 이름이 .NET MAUI Blazor .로 .NET MAUI Blazor Hybrid변경되었습니다.
  • ASP.NET Core Blazor Hybrid: BlazorWebViewTryDispatchAsync 지정된 Action<ServiceProvider> 비동기적으로 호출하고 구성 요소에서 사용할 수 Razor 있는 범위가 지정된 서비스를 전달하는 메서드를 가져옵니다. 이렇게 하면 네이티브 UI의 코드가 다음과 같은 NavigationManager범위가 지정된 서비스에 액세스할 수 있습니다.
  • ASP.NET Core Blazor Hybrid 라우팅 및 탐색: 구성 요소 로드가 BlazorWebView.StartPath 완료되면 속성을 사용하여 탐색 컨텍스트 Razor 내에서 Blazor 초기 탐색 경로를 얻거나 설정합니다.

[Parameter] 쿼리 문자열에서 제공된 경우 특성이 더 이상 필요하지 않습니다.

[Parameter] 쿼리 문자열에서 매개 변수를 제공할 때 특성이 더 이상 필요하지 않습니다.

- [Parameter]
  [SupplyParameterFromQuery]

SignalR

서버 시간 제한 및 Keep-Alive 간격을 설정하는 새로운 방법

ServerTimeout (기본값: 30초) 및 KeepAliveInterval (기본값: 15초) 에 HubConnectionBuilder직접 설정할 수 있습니다.

JavaScript 클라이언트에 대한 이전 접근 방식

다음 예제에서는 ASP.NET Core 7.0 이전의 기본값의 두 배인 값의 할당을 보여 있습니다.

var connection = new signalR.HubConnectionBuilder()
  .withUrl("/chatHub")
  .build();

connection.serverTimeoutInMilliseconds = 60000;
connection.keepAliveIntervalInMilliseconds = 30000;

JavaScript 클라이언트에 대한 새로운 접근 방식

다음 예제에서는 ASP.NET Core 8.0 이상에서 기본값의 두 배인 값을 할당하는 새로운 방법을 보여 줍니다.

var connection = new signalR.HubConnectionBuilder()
  .withUrl("/chatHub")
  .withServerTimeoutInMilliseconds(60000)
  .withKeepAliveIntervalInMilliseconds(30000)
  .build();

앱의 JavaScript 클라이언트 Blazor Server 에 대한 이전 접근 방식

다음 예제에서는 ASP.NET Core 7.0 이전의 기본값의 두 배인 값의 할당을 보여 있습니다.

Blazor.start({
  configureSignalR: function (builder) {
    let c = builder.build();
    c.serverTimeoutInMilliseconds = 60000;
    c.keepAliveIntervalInMilliseconds = 30000;
    builder.build = () => {
      return c;
    };
  }
});

서버 쪽 Blazor 앱의 JavaScript 클라이언트에 대한 새로운 접근 방식

다음 예제에서는 Web Apps에 대한 ASP.NET Core 8.0 이상에서 기본값의 두 배인 값을 할당하는 새로운 방법을 보여 줍니다Blazor Server.Blazor

Blazor 웹앱:

Blazor.start({
  circuit: {
    configureSignalR: function (builder) {
      builder.withServerTimeout(60000).withKeepAliveInterval(30000);
    }
  }
});

Blazor Server:

Blazor.start({
  configureSignalR: function (builder) {
    builder.withServerTimeout(60000).withKeepAliveInterval(30000);
  }
});

.NET 클라이언트에 대한 이전 접근 방식

다음 예제에서는 ASP.NET Core 7.0 이전의 기본값의 두 배인 값의 할당을 보여 있습니다.

var builder = new HubConnectionBuilder()
    .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
    .Build();

builder.ServerTimeout = TimeSpan.FromSeconds(60);
builder.KeepAliveInterval = TimeSpan.FromSeconds(30);

builder.On<string, string>("ReceiveMessage", (user, message) => ...

await builder.StartAsync();

.NET 클라이언트에 대한 새로운 접근 방식

다음 예제에서는 ASP.NET Core 8.0 이상에서 기본값의 두 배인 값을 할당하는 새로운 방법을 보여 줍니다.

var builder = new HubConnectionBuilder()
    .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
    .WithServerTimeout(TimeSpan.FromSeconds(60))
    .WithKeepAliveInterval(TimeSpan.FromSeconds(30))
    .Build();

builder.On<string, string>("ReceiveMessage", (user, message) => ...

await builder.StartAsync();

SignalR 상태 저장 다시 연결

SignalR 상태 저장 다시 연결은 네트워크 연결을 전환할 때 또는 짧은 일시적인 액세스 손실과 같이 네트워크 연결이 일시적으로 끊어진 클라이언트의 인식된 가동 중지 시간을 줄입니다.

상태 저장 다시 연결은 다음을 수행합니다.

  • 서버 및 클라이언트의 데이터를 일시적으로 버퍼링합니다.
  • 서버와 클라이언트가 수신한 메시지(ACK-ing)를 승인합니다.
  • 연결이 중지된 동안 전송되었을 수 있는 메시지를 반환하고 재생하는 경우를 인식합니다.

상태 저장 다시 연결은 ASP.NET Core 8.0 이상에서 사용할 수 있습니다.

서버 허브 엔드포인트와 클라이언트 모두에서 상태 저장 다시 연결에 옵트인합니다.

  • 다음 옵션을 사용하도록 서버 허브 엔드포인트 구성을 업데이트합니다.AllowStatefulReconnects

    app.MapHub<MyHub>("/hubName", options =>
    {
        options.AllowStatefulReconnects = true;
    });
    

    필요에 따라 서버에서 허용하는 최대 버퍼 크기(바이트)를 전역적으로 또는 옵션을 사용하여 특정 허브 StatefulReconnectBufferSize 에 대해 설정할 수 있습니다.

    옵션은 StatefulReconnectBufferSize 전역적으로 설정됩니다.

    builder.AddSignalR(o => o.StatefulReconnectBufferSize = 1000);
    

    StatefulReconnectBufferSize 특정 허브에 대해 설정된 옵션:

    builder.AddSignalR().AddHubOptions<MyHub>(o => o.StatefulReconnectBufferSize = 1000);
    

    StatefulReconnectBufferSize 옵션은 기본값이 100,000바이트인 선택 사항입니다.

  • JavaScript 또는 TypeScript 클라이언트 코드를 업데이트하여 옵션을 사용하도록 설정합니다.withStatefulReconnect

    const builder = new signalR.HubConnectionBuilder()
      .withUrl("/hubname")
      .withStatefulReconnect({ bufferSize: 1000 });  // Optional, defaults to 100,000
    const connection = builder.build();
    

    bufferSize 옵션은 기본값이 100,000바이트인 선택 사항입니다.

  • 옵션을 사용하도록 .NET 클라이언트 코드를 업데이트합니다 WithStatefulReconnect .

      var builder = new HubConnectionBuilder()
          .WithUrl("<hub url>")
          .WithStatefulReconnect();
      builder.Services.Configure<HubConnectionOptions>(o => o.StatefulReconnectBufferSize = 1000);
      var hubConnection = builder.Build();
    

    StatefulReconnectBufferSize 옵션은 기본값이 100,000바이트인 선택 사항입니다.

자세한 내용은 상태 저장 다시 연결 구성을 참조 하세요.

최소 API

이 섹션에서는 최소 API에 대한 새로운 기능에 대해 설명합니다. 최소 API와 관련된 자세한 내용은 네이티브 AOT의 섹션도 참조하세요.

사용자 재정의 문화권

ASP.NET Core 8.0부터 RequestLocalizationOptions.CultureInfoUseUserOverride 속성을 사용하면 애플리케이션에서 기본 설정이 NumberFormat 아닌 Windows 설정을 CultureInfoDateTimeFormat 사용할지 여부를 결정할 수 있습니다. 이는 Linux에 영향을 주지 않습니다. 이 값은 .에 UseUserOverride직접 해당합니다.

    app.UseRequestLocalization(options =>
    {
        options.CultureInfoUseUserOverride = false;
    });

양식에 바인딩

이제 [FromForm] 특성을 사용하여 양식 값에 대한 명시적 바인딩이 지원됩니다. 위조 방지 토큰을 포함하는 요청에 [FromForm] 바인딩된 매개 변수입니다. 위조 방지 토큰은 요청이 처리될 때 유효성을 검사합니다.

및 형식을 사용하여 폼에 IFormCollectionIFormFileIFormFileCollection 유추된 바인딩도 지원됩니다. OpenAPI 메타데이터는 Swagger UI와의 통합을 지원하기 위해 양식 매개 변수에 대해 유추됩니다.

자세한 내용은 다음을 참조하세요.

이제 양식에서 바인딩이 지원됩니다.

  • 컬렉션(예: 목록사전)
  • 복합 형식(예: TodoProject

자세한 내용은 양식의 컬렉션 및 복합 형식에 바인딩을 참조 하세요.

최소 API를 사용하여 위조 방지

이 릴리스는 사이트 간 요청 위조 공격을 완화하는 데 사용되는 위조 방지 토큰의 유효성을 검사하기 위한 미들웨어를 추가합니다. AddAntiforgery를 호출하여 DI에 위조 방지 서비스를 등록합니다. WebApplicationBuilder 는 위조 방지 서비스가 DI 컨테이너에 등록되었을 때 미들웨어를 자동으로 추가합니다. 위조 방지 토큰은 교차 사이트 요청 위조 공격을 완화하는 데 사용됩니다.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

app.MapGet("/", () => "Hello World!");

app.Run();

위조 방지 미들웨어:

  • 요청 파이프라인의 나머지 실행을 단락하지 않습니다.
  • 현재 요청의 HttpContext.Features에서 IAntiforgeryValidationFeature를 설정합니다.

위조 방지 토큰은 다음과 같은 경우에만 유효성을 검사합니다.

  • 엔드포인트에는 IAntiforgeryMetadata를 구현하는 메타데이터가 포함되어 있습니다RequiresValidation=true.
  • 엔드포인트와 연결된 HTTP 메서드는 관련 HTTP 메서드입니다. 관련 메서드는 TRACE, OPTIONS, HEAD 및 GET을 제외한 모든 HTTP 메서드 입니다.
  • 요청은 유효한 엔드포인트와 연결됩니다.

자세한 내용은 최소 API를 사용한 위조 방지를 참조 하세요.

의 새 IResettable 인터페이스 ObjectPool

Microsoft.Extensions.ObjectPool 은 메모리의 개체 인스턴스 풀링을 지원합니다. 값을 할당하거나 초기화하는 데 비용이 많이 드는 경우 앱에서 개체 풀을 사용할 수 있습니다.

이 릴리스에서는 인터페이스를 추가하여 개체 풀을 더 쉽게 사용할 수 있도록 했습니다 IResettable . 재사용 가능한 형식은 종종 사용 간에 기본 상태로 다시 설정해야 합니다. IResettable 형식은 개체 풀로 반환되면 자동으로 다시 설정됩니다.

자세한 내용은 ObjectPool 샘플을 참조 하세요.

네이티브 AOT

.NET 네이티브 AOT(Ahead-Of-Time)에 대한 지원이 추가되었습니다. AOT를 사용하여 게시되는 앱은 앱 크기가 작고 메모리 사용량이 적으며 시작 시간이 빨라집니다. 네이티브 AOT는 현재 gRPC, 최소 API 및 작업자 서비스 앱에서 지원됩니다. 자세한 내용은 ASP.NET Core에서 네이티브 AOT 및 자습서: Native AOT를 사용하여 ASP.NET Core 앱 게시를 참조하세요. ASP.NET Core 및 네이티브 AOT 호환성 관련 알려진 문제에 대한 자세한 내용은 GitHub 문제 dotnet/core #8288을 참조하세요.

라이브러리 및 네이티브 AOT

ASP.NET Core 프로젝트에 사용되는 많은 인기 라이브러리는 현재 Native AOT를 대상으로 하는 프로젝트에서 사용할 때 다음과 같은 호환성 문제가 있습니다.

  • 리플렉션을 사용하여 형식을 검사하고 검색합니다.
  • 런타임에 라이브러리를 조건부로 로드합니다.
  • 즉시 코드를 생성하여 기능을 구현합니다.

네이티브 AOT를 사용하려면 이러한 동적 기능을 사용하는 라이브러리를 업데이트해야 합니다. Roslyn 원본 생성기와 같은 도구를 사용하여 업데이트할 수 있습니다.

네이티브 AOT를 지원하려는 라이브러리 작성자는 다음을 권장합니다.

새 프로젝트 템플릿

ASP.NET Core Web API(네이티브 AOT) 프로젝트 템플릿(짧은 이름 webapiaot)은 AOT 게시를 사용하도록 설정된 프로젝트를 만듭니다. 자세한 내용은 Web API(네이티브 AOT) 템플릿을 참조 하세요.

CreateSlimBuilder 메서드

Web API(네이티브 AOT) 템플릿에서 사용되는 메서드는 CreateSlimBuilder() 앱을 실행하는 데 필요한 최소 ASP.NET Core 기능을 초기화 WebApplicationBuilder 합니다. 이 CreateSlimBuilder 메서드에는 효율적인 개발 환경에 일반적으로 필요한 다음 기능이 포함되어 있습니다.

  • JSON 파일 구성 및 appsettings.jsonappsettings.{EnvironmentName}.json.
  • 사용자 비밀 구성.
  • 콘솔 로깅.
  • 로깅 구성.

자세한 내용은 메서드 CreateSlimBuilder 를 참조하세요.

CreateEmptyBuilder 메서드

필요한 기능WebApplication.CreateEmptyBuilder(WebApplicationOptions options)만 포함하는 작은 앱을 빌드하기 위한 또 다른 새로운 WebApplicationBuilder 팩터리 방법이 있습니다. 기본 WebApplicationBuilder 제공 동작 없이 만들어집니다. 빌드하는 앱에는 명시적으로 구성된 서비스 및 미들웨어만 포함됩니다.

다음은 이 API를 사용하여 작은 웹 애플리케이션을 만드는 예제입니다.

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
builder.WebHost.UseKestrelCore();

var app = builder.Build();

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello, World!");
    await next(context);
});

Console.WriteLine("Running...");
app.Run();

Linux-x64 컴퓨터에서 .NET 8 미리 보기 7을 사용하여 네이티브 AOT로 이 코드를 게시하면 약 8.5MB의 자체 포함 네이티브 실행 파일이 생성됩니다.

구성 가능한 HTTPS 지원을 사용하여 앱 크기 감소

HTTPS 또는 HTTP/3 지원이 필요하지 않은 앱의 네이티브 AOT 이진 크기를 추가로 줄입니다. HTTPS 또는 HTTP/3을 사용하지 않는 것은 TLS 종료 프록시 뒤에서 실행되는 앱(예: Azure에서 호스트됨)에 일반적입니다. 새 WebApplication.CreateSlimBuilder 메서드는 기본적으로 이 기능을 생략합니다. HTTPS 또는 builder.WebHost.UseQuic() HTTP/3을 호출 builder.WebHost.UseKestrelHttpsConfiguration() 하여 추가할 수 있습니다. 자세한 내용은 메서드 CreateSlimBuilder 를 참조하세요.

JS컴파일러 생성 IAsyncEnumerable<T> 형식의 ON serialization

Native AOT를 더 잘 지원하기 위해 System.Text.Json 새로운 기능이 추가되었습니다. 이러한 새로운 기능은 AOT에서 리플렉션을 지원하지 않으므로 원본 생성 모드 System.Text.Json에 대한 기능을 추가합니다.

새로운 기능 중 하나는 C# 컴파일러에서 구현하는 구현의 IAsyncEnumerable<T> ON serialization을 지원하는 JS것입니다. 이 지원을 통해 네이티브 AOT를 게시하도록 구성된 ASP.NET Core 프로젝트에서 사용할 수 있습니다.

이 API는 경로 처리기가 열거형을 비동기적으로 반환하는 데 사용하는 yield return 시나리오에서 유용합니다. 예를 들어 데이터베이스 쿼리에서 행을 구체화합니다. 자세한 내용은 .NET 8 미리 보기 4 공지에서 말할 수 없는 형식 지원을 참조하세요.

원본 생성의 System.Text.Json 다른 개선 사항에 대한 자세한 내용은 .NET 8의 Serialization 개선 사항을 참조하세요.

트리밍 경고에 주석이 추가된 최상위 API

기본 진입점은 이제 Native AOT에서 안정적으로 작동하지 않는 하위 시스템에 주석을 추가합니다. 네이티브 AOT를 사용하도록 설정된 애플리케이션에서 이러한 메서드를 호출하면 경고가 제공됩니다. 예를 들어 다음 코드는 이 API가 트리밍이 안전하지 않고 네이티브 AOT에서 지원되지 않기 때문에 호출 AddControllers 시 경고를 생성합니다.

MVC가 현재 Native AOT를 지원하지 않는다는 AddControllers 메서드의 IL2026 경고 메시지를 보여 주는 Visual Studio 창

요청 대리자 생성기

최소 API가 네이티브 AOT와 호환되도록 RDG(요청 대리자 생성기)가 도입되었습니다. RDG는 (RDF)가 수행하는 작업을 RequestDelegateFactory 수행하는 원본 생성기입니다. 즉, 다양한 MapGet()MapPost()경로와 같은 호출을 지정된 경로와 연결된 인스턴스로 RequestDelegate 바꿉니다. 하지만 RDG는 애플리케이션이 시작될 때 메모리 내 작업을 수행하는 대신 컴파일 시간에 이를 수행하고 프로젝트에 직접 C# 코드를 생성합니다. The RDG:

  • 이 코드의 런타임 생성을 제거합니다.
  • API에 사용되는 형식을 네이티브 AOT 도구 체인에서 정적으로 분석할 수 있는지 확인합니다.
  • 필요한 코드가 잘리지 않도록 합니다.

가능한 한 많은 최소 API 기능이 RDG에서 지원되므로 네이티브 AOT와 호환되도록 노력하고 있습니다.

Native AOT를 사용하여 게시를 사용하도록 설정하면 프로젝트에서 RDG가 자동으로 사용하도록 설정됩니다. 프로젝트 파일에서 설정하여 네이티브 AOT를 사용하지 않는 경우에도 RDG를 수동으로 사용하도록 설정할 <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> 수 있습니다. 이 기능은 처음에 Native AOT에 대한 프로젝트의 준비 상태를 평가하거나 앱의 시작 시간을 줄일 때 유용할 수 있습니다.

인터셉터를 사용하여 성능 향상

요청 대리자 생성기는 새 C# 12 인터셉터 컴파일러 기능을 사용하여 런타임에 정적으로 생성된 변형을 사용하여 최소 API 메서드에 대한 호출을 가로채도록 지원합니다. 인터셉터를 사용하면 .으로 컴파일된 앱의 시작 성능이 향상됩니다 PublishAot.

컴파일 시간에서 로깅 및 예외 처리가 최소 API 생성됨

런타임에 생성된 최소 API는 매개 변수 바인딩이 실패할 때 자동으로 로깅(또는 개발 환경에서 예외 throw)을 지원합니다. .NET 8은 RDG(요청 대리자 생성기)를 통해 컴파일 시간에 생성된 API에 대해 동일한 지원을 제공합니다. 자세한 내용은 컴파일 시간 생성 최소 API의 로깅 및 예외 처리를 참조 하세요.

AOT 및 System.Text.Json

최소 API는 ON 페이로드System.Text.Json를 받고 반환하는 데 JS최적화되어 있으므로 ON 및 Native AOT에 대한 JS호환성 요구 사항도 적용됩니다. 네이티브 AOT 호환성을 사용하려면 원본 생성기를 System.Text.Json 사용해야 합니다. 최소 API의 요청 대리자에서 매개 변수로 허용되거나 반환되는 모든 형식은 ASP.NET Core의 종속성 주입을 통해 등록된 형식에 대해 구성 JsonSerializerContext 되어야 합니다. 예를 들면 다음과 같습니다.

// Register the JSON serializer context with DI
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

...

// Add types used in the minimal API app to source generated JSON serializer content
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{

}

API에 TypeInfoResolverChain 대한 자세한 내용은 다음 리소스를 참조하세요.

라이브러리 및 네이티브 AOT

현재 ASP.NET Core 프로젝트에 사용할 수 있는 많은 공통 라이브러리는 Native AOT를 대상으로 하는 프로젝트에서 사용되는 경우 일부 호환성 문제가 있습니다. 널리 사용되는 라이브러리는 .NET 리플렉션의 동적 기능을 사용하여 형식을 검사 및 검색하고, 런타임에 조건부로 라이브러리를 로드하고, 즉시 코드를 생성하여 해당 기능을 구현합니다. Roslyn 원본 생성기와 같은 도구를 사용하여 네이티브 AOT를 사용하려면 이러한 라이브러리를 업데이트해야 합니다.

Native AOT용 라이브러리를 준비하는 방법에 대해 자세히 알아보려는 라이브러리 작성자는 네이티브 AOT 호환성 요구 사항에 대해 자세히 알아보고 트리밍을 위해 라이브러리를 준비하여 시작하는 것이 좋습니다.

Kestrel 서버 및 HTTP.sys

HTTP.sys 몇 Kestrel 가지 새로운 기능이 있습니다.

에서 명명된 파이프에 대한 지원 Kestrel

명명된 파이프는 Windows 앱 간에 IPC(프로세스 간 통신)를 빌드하는 데 널리 사용되는 기술입니다. 이제 .NET Kestrel및 명명된 파이프를 사용하여 IPC 서버를 빌드할 수 있습니다.

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenNamedPipe("MyPipeName");
});

이 기능 및 .NET 및 gRPC를 사용하여 IPC 서버 및 클라이언트를 만드는 방법에 대한 자세한 내용은 gRPC와의 프로세스 간 통신을 참조하세요.

명명된 파이프 전송 성능 향상

명명된 파이프 연결 성능이 향상되었습니다. Kestrel'의 명명된 파이프 전송은 이제 병렬로 연결을 허용하고 인스턴스를 NamedPipeServerStream 다시 사용합니다.

100,000개의 연결을 만드는 시간:

  • 이전: 5.916초
  • 후: 2.374초

의 macOS에서 TLS(HTTPS)를 통한 HTTP/2 지원 Kestrel

.NET 8은 macOS에 ALPN(애플리케이션 계층 프로토콜 협상)에 대한 지원을 추가합니다. ALPN은 연결에서 사용할 HTTP 프로토콜을 협상하는 데 사용되는 TLS 기능입니다. 예를 들어 ALPN을 사용하면 브라우저 및 기타 HTTP 클라이언트가 HTTP/2 연결을 요청할 수 있습니다. 이 기능은 HTTP/2가 필요한 gRPC 앱에 특히 유용합니다. 자세한 내용은 ASP.NET Core Kestrel 웹 서버에서 HTTP/2 사용을 참조하세요.

에서 보고 있는 인증서 파일 Kestrel

경로에 의해 구성된 TLS 인증서는 이제 전달될 때 reloadOnChange 변경 내용을 모니터링합니다 KestrelServerOptions.Configure(). 인증서 파일에 대한 변경 내용은 구성된 경로 변경(즉, 엔드포인트가 다시 로드됨)과 동일한 방식으로 처리됩니다.

파일 삭제는 일시적으로 발생하고 일시적이지 않은 경우 서버가 충돌하기 때문에 특히 추적되지 않습니다.

지정된 HTTP 프로토콜이 사용되지 않는 경우 경고

TLS를 사용하지 않도록 설정했고 HTTP/1.x를 사용할 수 있는 경우 HTTP/2 및 HTTP/3은 지정된 경우에도 사용하지 않도록 설정됩니다. 이로 인해 몇 가지 불쾌한 놀라움이 발생할 수 있으므로 경고 출력을 추가하여 언제 발생하는지 알려 줍니다.

HTTP_PORTS 키 및 HTTPS_PORTS 구성

애플리케이션 및 컨테이너는 종종 호스트 또는 경로와 같은 추가 제약 조건 없이 80과 같이 수신 대기할 포트만 제공됩니다. HTTP_PORTSHTTPS_PORTS HTTP.sys 서버에 대한 Kestrel 수신 대기 포트를 지정할 수 있는 새 구성 키입니다. 이러한 접두사는 환경 변수 접두사를 사용하여 DOTNET_ 정의하거나 ASPNETCORE_ appsettings.json 같은 다른 구성 입력을 통해 직접 지정할 수 있습니다. 각각은 포트 값의 세미콜론으로 구분된 목록입니다. 예시:

ASPNETCORE_HTTP_PORTS=80;8080
ASPNETCORE_HTTPS_PORTS=443;8081

이는 스키마(HTTP 또는 HTTPS) 및 호스트 또는 IP를 지정하는 다음의 약식입니다.

ASPNETCORE_URLS=http://*:80/;http://*:8080/;https://*:443/;https://*:8081/

자세한 내용은 ASP.NET Core에서 ASP.NET Core Kestrel 웹 서버HTTP.sys 웹 서버 구현에 대한 엔드포인트 구성을 참조하세요.

ITlsHandshakeFeature의 SNI 호스트 이름

이제 SNI(서버 이름 표시) 호스트 이름이 인터페이스의 HostName 속성에 ITlsHandshakeFeature 노출됩니다.

SNI는 TLS 핸드셰이크 프로세스의 일부입니다. 이를 통해 클라이언트는 서버가 여러 가상 호스트를 호스트하거나 기본 때 연결하려는 호스트 이름을 지정할 수 있습니다. 핸드셰이크 프로세스 중에 올바른 보안 인증서를 표시하려면 서버에서 각 요청에 대해 선택된 호스트 이름을 알고 있어야 합니다.

일반적으로 호스트 이름은 TLS 스택 내에서만 처리되며 일치하는 인증서를 선택하는 데 사용됩니다. 그러나 이를 노출하면 앱의 다른 구성 요소는 진단, 속도 제한, 라우팅 및 청구와 같은 목적으로 해당 정보를 사용할 수 있습니다.

호스트 이름을 노출하는 것은 수천 개의 SNI 바인딩을 관리하는 대규모 서비스에 유용합니다. 이 기능은 고객 에스컬레이션 중에 디버깅 효율성을 크게 향상시킬 수 있습니다. 투명성이 향상되어 문제 해결 속도가 빨라지고 서비스 안정성이 향상됩니다.

자세한 내용은 ITlsHandshakeFeature.HostName을 참조하세요.

IHttpSysRequestTimingFeature

IHttpSysRequestTimingFeature는 IIS에서 HTTP.sys 서버In-process 호스팅을 사용할 때 요청에 대한 자세한 타이밍 정보를 제공합니다.

  • 타임스탬프는 QueryPerformanceCounter를 사용하여 가져옵니다.
  • 타임스탬프 빈도는 QueryPerformanceFrequency를 통해 가져올 수 있습니다.
  • 타이밍의 인덱스를 HttpSysRequestTimingType으로 캐스팅하여 타이밍이 나타내는 것을 알 수 있습니다.
  • 현재 요청에 타이밍을 사용할 수 없는 경우 값은 0일 수 있습니다.

IHttpSysRequestTimingFeature.TryGetTimestamp 는 제공된 타이밍 형식에 대한 타임스탬프를 검색합니다.

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;
var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys();

var app = builder.Build();

app.Use((context, next) =>
{
    var feature = context.Features.GetRequiredFeature<IHttpSysRequestTimingFeature>();

    var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
    var logger = loggerFactory.CreateLogger("Sample");

    var timingType = HttpSysRequestTimingType.RequestRoutingEnd;

    if (feature.TryGetTimestamp(timingType, out var timestamp))
    {
        logger.LogInformation("Timestamp {timingType}: {timestamp}",
                                          timingType, timestamp);
    }
    else
    {
        logger.LogInformation("Timestamp {timingType}: not available for the "
                                           + "current request",    timingType);
    }

    return next(context);
});

app.MapGet("/", () => Results.Ok());

app.Run();

자세한 내용은 IHttpSysRequestTimingFeature 및 타이밍 정보 및 IIS를 사용한 In-process 호스팅을 사용하여 자세한 타이밍 정보 가져오기를 참조하세요.

HTTP.sys: 커널 모드 응답 버퍼링에 대한 옵트인 지원

일부 시나리오에서는 대기 시간이 긴 작은 쓰기의 양이 많으면 성능에 상당한 영향을 줄 HTTP.sys수 있습니다. 이 영향은 구현에 버퍼가 Pipe 없기 때문입니다 HTTP.sys . 이러한 시나리오에서 성능을 향상시키기 위해 응답 버퍼링에 대한 지원이 추가 HTTP.sys되었습니다. HttpSysOptions.EnableKernelResponseBuffering을 .로 설정하여 버퍼링을true사용하도록 설정합니다.

응답 버퍼링은 동기 I/O를 수행하는 앱 또는 한 번에 둘 이상의 미해결 쓰기가 없는 비동기 I/O에서 사용하도록 설정해야 합니다. 이러한 시나리오에서 응답 버퍼링은 대기 시간이 긴 연결에 대한 처리량을 크게 향상시킬 수 있습니다.

비동기 I/O를 사용하고 한 번에 둘 이상의 쓰기가 미해결된 앱은 이 플래그를 사용하지 않아야 합니다. 이 플래그를 사용하도록 설정하면 HTTP.Sys에서 CPU 및 메모리 사용량이 높아질 수 있습니다.

인증 및 권한 부여

ASP.NET Core 8은 인증 및 권한 부여에 새로운 기능을 추가합니다.

Identity API 엔드포인트

MapIdentityApi<TUser> 는 두 개의 API 엔드포인트(/register/login)를 추가하는 새 확장 메서드입니다. 기본 목표는 MapIdentityApi 개발자가 JavaScript 기반 SPA(단일 페이지 앱) 또는 Blazor 앱에서 인증에 ASP.NET Core Identity 를 쉽게 사용할 수 있도록 하는 것입니다. MapIdentityApi는 Pages를 기반으로 하는 ASP.NET CoreIdentity에서 Razor 제공하는 기본 UI를 사용하는 대신 SPA 앱 및 비브로우저 앱에 더 적합한 ON API 엔드포인트를 추가JS합니다. 자세한 내용은 API 엔드포인트를 참조 Identity 하세요.

IAuthorizationRequirementData

Core 8을 ASP.NET 전에 다음을 구현해야 하는 엔드포인트에 매개 변수가 있는 권한 부여 정책을 추가합니다.

  • AuthorizeAttribute 각 정책에 대해
  • AuthorizationPolicyProvider 문자열 기반 계약에서 사용자 지정 정책을 처리합니다.
  • AuthorizationRequirement 을 선택합니다.
  • AuthorizationHandler 각 요구 사항에 대한

예를 들어 ASP.NET Core 7.0용으로 작성된 다음 샘플을 고려합니다.

using AuthRequirementsData.Authorization;
using Microsoft.AspNetCore.Authorization;

var builder = WebApplication.CreateBuilder();

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddControllers();
builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();

var app = builder.Build();

app.MapControllers();

app.Run();
using Microsoft.AspNetCore.Mvc;

namespace AuthRequirementsData.Controllers;

[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
    [MinimumAgeAuthorize(16)]
    [HttpGet("hello")]
    public string Hello() => $"Hello {(HttpContext.User.Identity?.Name ?? "world")}!";
}
using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Security.Claims;

namespace AuthRequirementsData.Authorization;

class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;

    public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
    {
        _logger = logger;
    }

    // Check whether a given MinimumAgeRequirement is satisfied or not for a particular
    // context.
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                               MinimumAgeRequirement requirement)
    {
        // Log as a warning so that it's very clear in sample output which authorization
        // policies(and requirements/handlers) are in use.
        _logger.LogWarning("Evaluating authorization requirement for age >= {age}",
                                                                    requirement.Age);

        // Check the user's age
        var dateOfBirthClaim = context.User.FindFirst(c => c.Type ==
                                                                 ClaimTypes.DateOfBirth);
        if (dateOfBirthClaim != null)
        {
            // If the user has a date of birth claim, check their age
            var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value, CultureInfo.InvariantCulture);
            var age = DateTime.Now.Year - dateOfBirth.Year;
            if (dateOfBirth > DateTime.Now.AddYears(-age))
            {
                // Adjust age if the user hasn't had a birthday yet this year.
                age--;
            }

            // If the user meets the age criterion, mark the authorization requirement
            // succeeded.
            if (age >= requirement.Age)
            {
                _logger.LogInformation("Minimum age authorization requirement {age} satisfied",
                                         requirement.Age);
                context.Succeed(requirement);
            }
            else
            {
                _logger.LogInformation("Current user's DateOfBirth claim ({dateOfBirth})" +
                    " does not satisfy the minimum age authorization requirement {age}",
                    dateOfBirthClaim.Value,
                    requirement.Age);
            }
        }
        else
        {
            _logger.LogInformation("No DateOfBirth claim present");
        }

        return Task.CompletedTask;
    }
}

전체 샘플은 AspNetCore.Docs.Samples 리포지토리에 있습니다.

ASP.NET Core 8에는 인터페이스가 IAuthorizationRequirementData 도입되었습니다. IAuthorizationRequirementData 인터페이스를 사용하면 특성 정의가 권한 부여 정책과 관련된 요구 사항을 지정할 수 있습니다. 사용 하 여 IAuthorizationRequirementData이전 사용자 지정 권한 부여 정책 코드를 적은 코드 줄로 작성할 수 있습니다. 업데이트 Program.cs 된 파일:

  using AuthRequirementsData.Authorization;
  using Microsoft.AspNetCore.Authorization;
  
  var builder = WebApplication.CreateBuilder();
  
  builder.Services.AddAuthentication().AddJwtBearer();
  builder.Services.AddAuthorization();
  builder.Services.AddControllers();
- builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
  builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();
  
  var app = builder.Build();
  
  app.MapControllers();
  
  app.Run();

업데이트 MinimumAgeAuthorizationHandler된 내용:

using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Security.Claims;

namespace AuthRequirementsData.Authorization;

- class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement>
+ class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
{
    private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;

    public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
    {
        _logger = logger;
    }

    // Check whether a given MinimumAgeRequirement is satisfied or not for a particular
    // context
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
-                                              MinimumAgeRequirement requirement)
+                                              MinimumAgeAuthorizeAttribute requirement)
    {
        // Remaining code omitted for brevity.

업데이트된 전체 샘플은 여기에서 찾을 수 있습니다.

새 샘플에 대한 자세한 검사는 IAuthorizationRequirementData를 사용한 사용자 지정 권한 부여 정책을 참조하세요.

Swagger UI 엔드포인트 보안

이제 Swagger UI 엔드포인트를 호출 MapSwagger().RequireAuthorization하여 프로덕션 환경에서 보안을 설정할 수 있습니다. 자세한 내용은 Swagger UI 엔드포인트 보안을 참조 하세요.

기타

다음 섹션에서는 ASP.NET Core 8의 기타 새로운 기능에 대해 설명합니다.

종속성 주입에서 키 지정된 서비스 지원

키 서비스는 키를 사용하여 DI(종속성 주입) 서비스를 등록하고 검색하는 메커니즘을 나타냅니다. 서비스는 키를 등록하기 위해 호출 AddKeyedSingleton (또는 AddKeyedScopedAddKeyedTransient)하여 키와 연결됩니다. 특성을 사용하여 키를 [FromKeyedServices] 지정하여 등록된 서비스에 액세스합니다. 다음 코드는 키 지정된 서비스를 사용하는 방법을 보여 줍니다.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
builder.Services.AddControllers();

var app = builder.Build();

app.MapGet("/big", ([FromKeyedServices("big")] ICache bigCache) => bigCache.Get("date"));
app.MapGet("/small", ([FromKeyedServices("small")] ICache smallCache) =>
                                                               smallCache.Get("date"));

app.MapControllers();

app.Run();

public interface ICache
{
    object Get(string key);
}
public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

[ApiController]
[Route("/cache")]
public class CustomServicesApiController : Controller
{
    [HttpGet("big-cache")]
    public ActionResult<object> GetOk([FromKeyedServices("big")] ICache cache)
    {
        return cache.Get("data-mvc");
    }
}

public class MyHub : Hub
{
    public void Method([FromKeyedServices("small")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }
}

ASP.NET Core 백 엔드를 사용하는 SPA 앱용 Visual Studio 프로젝트 템플릿

Visual Studio 프로젝트 템플릿은 이제 ASP.NET Core 백 엔드가 있는 SPA(단일 페이지 앱)를 만드는 권장 방법입니다. JavaScript 프레임워크 Angular, ReactVue를 기반으로 앱을 만드는 템플릿이 제공됩니다. 다음 템플릿:

  • 프런트 엔드 프로젝트와 백 엔드 프로젝트를 사용하여 Visual Studio 솔루션을 만듭니다.
  • 프런트 엔드에는 JavaScript 및 TypeScript(.esproj)에 Visual Studio 프로젝트 형식을 사용합니다.
  • 백 엔드에 ASP.NET Core 프로젝트를 사용합니다.

Visual Studio 템플릿 및 레거시 템플릿에 액세스하는 방법에 대한 자세한 내용은 ASP.NET Core의 SPA(단일 페이지 앱) 개요를 참조 하세요.

제네릭 특성 지원

이전에 매개 변수가 필요했던 Type 특성은 이제 클린er 제네릭 변형에서 사용할 수 있습니다. 이는 C# 11의 제네릭 특성을 지원하여 가능합니다. 예를 들어 작업의 응답 형식에 주석을 추가하기 위한 구문은 다음과 같이 수정할 수 있습니다.

[ApiController]
[Route("api/[controller]")]
public class TodosController : Controller
{
  [HttpGet("/")]
- [ProducesResponseType(typeof(Todo), StatusCodes.Status200OK)]
+ [ProducesResponseType<Todo>(StatusCodes.Status200OK)]
  public Todo Get() => new Todo(1, "Write a sample", DateTime.Now, false);
}

제네릭 변형은 다음 특성에 대해 지원됩니다.

  • [ProducesResponseType<T>]
  • [Produces<T>]
  • [MiddlewareFilter<T>]
  • [ModelBinder<T>]
  • [ModelMetadataType<T>]
  • [ServiceFilter<T>]
  • [TypeFilter<T>]

ASP.NET Core 앱의 코드 분석

다음 표에 표시된 새 분석기는 ASP.NET Core 8.0에서 사용할 수 있습니다.

진단 ID 호환성이 손상됨 또는 호환성이 손상되지 않음 설명
ASP0016 호환성이 손상되지 않음 RequestDelegate에서 값을 반환하지 마세요.
ASP0019 호환성이 손상되지 않음 IHeaderDictionary.Append 또는 인덱서 사용 제안
ASP0020 호환성이 손상되지 않음 경로 매개 변수에서 참조하는 복합 형식은 구문 분석 가능해야 합니다.
ASP0021 호환성이 손상되지 않음 BindAsync 메서드의 반환 형식은 ValueTask<T>
ASP0022 호환성이 손상되지 않음 경로 처리기 간에 경로 충돌이 감지됨
ASP0023 호환성이 손상되지 않음 MVC: 경로 처리기 간에 경로 충돌이 감지됨
ASP0024 호환성이 손상되지 않음 경로 처리기에 특성이 있는 여러 매개 변수가 있습니다 [FromBody] .
ASP0025 호환성이 손상되지 않음 AddAuthorizationBuilder 사용

경로 도구

ASP.NET Core는 라우팅을 기반으로 합니다. 최소 API, 웹 API, Razor 페이지 및 Blazor 모든 경로는 HTTP 요청이 코드에 매핑되는 방법을 사용자 지정합니다.

.NET 8에서는 라우팅을 더 쉽게 학습하고 사용할 수 있도록 새로운 기능 제품군에 투자했습니다. 이러한 새로운 기능은 다음과 같습니다.

자세한 내용은 .NET 8의 경로 도구를 참조하세요.

ASP.NET Core 메트릭

메트릭은 시간에 따라 보고되는 측정값이며 앱의 상태를 모니터링하고 경고를 생성하는 데 가장 자주 사용됩니다. 예를 들어 실패한 HTTP 요청을 보고하는 카운터는 대시보드에 표시되거나 오류가 임계값을 초과할 때 경고를 생성할 수 있습니다.

이 미리 보기는 를 사용하여 System.Diagnostics.MetricsASP.NET Core 전체에 새 메트릭을 추가합니다. Metrics 는 앱에 대한 정보를 보고하고 수집하기 위한 최신 API입니다.

메트릭은 기존 이벤트 카운터에 비해 많은 개선 사항을 제공합니다.

  • 카운터, 계기 및 히스토그램을 사용하는 새로운 종류의 측정입니다.
  • 다차원 값을 사용한 강력한 보고
  • OpenTelemetry 표준에 맞춰 더 넓은 클라우드 네이티브 에코시스템에 통합합니다.

ASP.NET Core 호스팅 Kestrel에 대한 메트릭이 SignalR추가되었습니다. 자세한 내용은 System.Diagnostics.Metrics를 참조하세요.

IExceptionHandler

IExceptionHandler 는 개발자가 중앙 위치에서 알려진 예외를 처리하기 위한 콜백을 제공하는 새로운 인터페이스입니다.

IExceptionHandler 구현은 호출 IServiceCollection.AddExceptionHandler<T>하여 등록됩니다. 여러 구현을 추가할 수 있으며 등록된 순서대로 호출됩니다. 예외 처리기가 요청을 처리하는 경우 처리를 중지하도록 반환 true 할 수 있습니다. 예외 처리기가 예외를 처리하지 않는 경우 컨트롤은 미들웨어의 기본 동작 및 옵션으로 대체됩니다.

자세한 내용은 IExceptionHandler를 참조하세요.

향상된 디버깅 환경

디버그 사용자 지정 특성이 , , ClaimsPrincipalHttpRequestHttpResponseWebApplication. 같은 HttpContext형식에 추가되었습니다. 이러한 형식에 대한 향상된 디버거 디스플레이를 사용하면 IDE의 디버거에서 중요한 정보를 더 쉽게 찾을 수 있습니다. 다음 스크린샷은 이러한 특성이 디버거의 표시 HttpContext에서 만드는 차이점을 보여 줍니다.

.NET 7:

.NET 7에서 HttpContext 형식의 도움이 되지 않는 디버거 표시

.NET 8:

.NET 8에서 HttpContext 형식의 유용한 디버거 표시

구성된 엔드포인트, 미들웨어 및 값과 IConfiguration 같은 중요한 정보를 강조 표시하기 위한 WebApplication 디버거 디스플레이입니다.

.NET 7:

.NET 7에서 WebApplication 형식의 도움이 되지 않는 디버거 표시

.NET 8:

.NET 8에서 WebApplication 형식의 유용한 디버거 표시

.NET 8의 디버깅 개선 사항에 대한 자세한 내용은 다음을 참조하세요.

IPNetwork.ParseTryParse

CIDR 표기법 또는 "슬래시 표기법"에서 입력 문자열을 사용하여 만들기 IPNetwork 를 지원하는 새 Parse 메서드와 TryParse 메서드 IPNetwork 를 추가합니다.

IPv4 예제는 다음과 같습니다.

// Using Parse
var network = IPNetwork.Parse("192.168.0.1/32");
// Using TryParse
bool success = IPNetwork.TryParse("192.168.0.1/32", out var network);
// Constructor equivalent
var network = new IPNetwork(IPAddress.Parse("192.168.0.1"), 32);

IPv6의 예는 다음과 같습니다.

// Using Parse
var network = IPNetwork.Parse("2001:db8:3c4d::1/128");
// Using TryParse
bool success = IPNetwork.TryParse("2001:db8:3c4d::1/128", out var network);
// Constructor equivalent
var network = new IPNetwork(IPAddress.Parse("2001:db8:3c4d::1"), 128);

Redis 기반 출력 캐싱

ASP.NET Core 8은 Redis를 출력 캐싱을 위한 분산 캐시로 사용하기 위한 지원을 추가합니다. 출력 캐싱은 앱이 최소 API 엔드포인트, 컨트롤러 작업 또는 Razor 페이지의 출력을 캐시할 수 있도록 하는 기능입니다. 자세한 내용은 출력 캐싱을 참조 하세요.

라우팅 후 단락 미들웨어

라우팅이 엔드포인트와 일치하는 경우 일반적으로 엔드포인트 논리를 호출하기 전에 나머지 미들웨어 파이프라인을 실행할 수 있습니다. 서비스는 파이프라인 초기에 알려진 요청을 필터링하여 리소스 사용량을 줄일 수 있습니다. 확장 메서드를 ShortCircuit 사용하여 라우팅이 엔드포인트 논리를 즉시 호출한 다음 요청을 종료하도록 합니다. 예를 들어 지정된 경로는 인증 또는 CORS 미들웨어를 통과하지 않아도 될 수 있습니다. 다음 예제에서는 경로와 일치하는 /short-circuit 단락 요청을 제공합니다.

app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();

이 메서드를 MapShortCircuit 사용하여 URL 접두사 매개 변수 배열을 전달하여 한 번에 여러 경로에 대한 단락을 설정합니다. 예를 들어 브라우저와 봇은 종종 서버에서 잘 알려진 경로(예: robots.txtfavicon.ico.)를 검색합니다. 앱에 해당 파일이 없는 경우 한 줄의 코드가 두 경로를 모두 구성할 수 있습니다.

app.MapShortCircuit(404, "robots.txt", "favicon.ico");

자세한 내용은 라우팅 후 단락 미들웨어를 참조 하세요.

HTTP 로깅 미들웨어 확장성

HTTP 로깅 미들웨어에는 다음과 같은 몇 가지 새로운 기능이 있습니다.

  • HttpLoggingFields.Duration: 사용하도록 설정하면 미들웨어는 요청 및 응답이 끝날 때 처리에 걸린 총 시간을 측정하는 새 로그를 내보낸다. 이 새 필드가 집합에 HttpLoggingFields.All 추가되었습니다.
  • HttpLoggingOptions.CombineLogs: 사용하도록 설정하면 미들웨어는 요청 및 응답에 대해 활성화된 모든 로그를 마지막에 하나의 로그로 통합합니다. 단일 로그 메시지에는 요청, 요청 본문, 응답, 응답 본문 및 기간이 포함됩니다.
  • IHttpLoggingInterceptor: 어떤 세부 정보가 기록되는지 사용자 지정하기 위해 요청당 및 응답별 콜백을 수신하기 위해 구현 및 등록(사용 AddHttpLoggingInterceptor)할 수 있는 서비스에 대한 새 인터페이스입니다. 엔드포인트별 로그 설정이 먼저 적용된 다음 이러한 콜백에서 재정의될 수 있습니다. 구현은 다음을 수행할 수 있습니다.
    • 요청 및 응답을 검사합니다.
    • 을 사용하거나 사용하지 않도록 설정합니다 HttpLoggingFields.
    • 기록되는 요청 또는 응답 본문의 양을 조정합니다.
    • 로그에 사용자 지정 필드를 추가합니다.

자세한 내용은 .NET Core 및 ASP.NET Core의 HTTP 로깅을 참조 하세요.

더 탄력적인 통합을 지원하기 위한 ProblemDetails의 새로운 API

.NET 7에서는 ProblemDetails 사양을 준수하는 오류 응답을 생성하는 환경을 개선하기 위해 ProblemDetails 서비스가 도입되었습니다. .NET 8에서는 생성ProblemDetails할 수 없는 경우 IProblemDetailsService 대체 동작을 보다 쉽게 구현할 수 있도록 새 API가 추가되었습니다. 다음 예제에서는 새 TryWriteAsync API를 사용하는 방법을 보여 줍니다.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler(exceptionHandlerApp =>
{
    exceptionHandlerApp.Run(async httpContext =>
    {
        var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
        if (pds == null
            || !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
        {
            // Fallback behavior
            await httpContext.Response.WriteAsync("Fallback: An error occurred.");
        }
    });
});

app.MapGet("/exception", () =>
{
    throw new InvalidOperationException("Sample Exception");
});

app.MapGet("/", () => "Test by calling /exception");

app.Run();

자세한 내용은 IProblemDetailsService 대체를 참조 하세요.

추가 리소스