ASP.NET Core 2.2에서 3.0으로 마이그레이션
작성자: Scott Addie 및 Rick Anderson
이 문서에서는 기존 ASP.NET Core 2.2 프로젝트를 ASP.NET Core 3.0으로 업데이트하는 방법을 설명합니다. 새 ASP.NET Core 3.0 프로젝트를 만들면 다음과 같은 작업을 수행할 수 있습니다.
- ASP.NET Core 2.2 코드와 비교합니다.
- 관련 변경 내용을 ASP.NET Core 3.0 프로젝트에 복사합니다.
필수 조건
- ASP.NET 및 웹 개발 워크로드가 있는 Visual Studio 2019
- .NET Core 3.0 SDK
에서 .NET Core SDK 버전 업데이트 global.json
솔루션이 특정 .NET Core SDK 버전을 대상으로 하는 파일을 사용하는 global.json 경우 해당 version
속성을 컴퓨터에 설치된 3.0 버전으로 업데이트합니다.
{
"sdk": {
"version": "3.0.100"
}
}
프로젝트 파일 업데이트
대상 프레임워크 업데이트
ASP.NET Core 3.0 이상은 .NET Core에서만 실행됩니다. TFM(대상 프레임워크 모니커)을 netcoreapp3.0
으로 설정합니다.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
사용되지 않는 패키지 참조 제거
많은 수의 NuGet 패키지가 ASP.NET Core 3.0에 대해 생성되지 않습니다. 프로젝트 파일에서 이러한 패키지 참조를 제거해야 합니다. ASP.NET Core 2.2 웹앱의 다음 프로젝트 파일을 살펴보겠습니다.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App"/>
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
</ItemGroup>
</Project>
ASP.NET Core 3.0에 대해 업데이트된 프로젝트 파일:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
업데이트된 ASP.NET Core 3.0 프로젝트 파일:
<PropertyGroup>
에서- TFM을
netcoreapp3.0
으로 업데이트합니다. <AspNetCoreHostingModel>
요소를 제거합니다. 자세한 내용은 본 문서의 In-Process 호스팅 모델을 참조하세요.
- TFM을
<ItemGroup>
에서Microsoft.AspNetCore.App
이 제거됩니다. 자세한 내용은 본 문서의 프레임워크 참조를 참조하세요.Microsoft.AspNetCore.Razor.Design
이 제거되고 후속 패키지 목록에서 더 이상 생성되지 않습니다.
더 이상 생성되지 않는 패키지의 전체 목록을 보려면 다음 확장 목록을 선택하세요.
더 이상 생성되지 않는 패키지 목록을 확장하려면 클릭하세요
- Microsoft.AspNetCore
- Microsoft.AspNetCore.All
- Microsoft.AspNetCore.App
- Microsoft.AspNetCore.Antiforgery
- Microsoft.AspNetCore.Authentication
- Microsoft.AspNetCore.Authentication.Abstractions
- Microsoft.AspNetCore.Authentication.Cookies
- Microsoft.AspNetCore.Authentication.Core
- Microsoft.AspNetCore.Authentication.OAuth
- Microsoft.AspNetCore.Authorization.Policy
- Microsoft.AspNetCore.CookiePolicy
- Microsoft.AspNetCore.Cors
- Microsoft.AspNetCore.Diagnostics
- Microsoft.AspNetCore.Diagnostics.HealthChecks
- Microsoft.AspNetCore.HostFiltering
- Microsoft.AspNetCore.Hosting
- Microsoft.AspNetCore.Hosting.Abstractions
- Microsoft.AspNetCore.Hosting.Server.Abstractions
- Microsoft.AspNetCore.Http
- Microsoft.AspNetCore.Http.Abstractions
- Microsoft.AspNetCore.Http.Connections
- Microsoft.AspNetCore.Http.Extensions
- Microsoft.AspNetCore.HttpOverrides
- Microsoft.AspNetCore.HttpsPolicy
- Microsoft.AspNetCore.Identity
- Microsoft.AspNetCore.Localization
- Microsoft.AspNetCore.Localization.Routing
- Microsoft.AspNetCore.Mvc
- Microsoft.AspNetCore.Mvc.Abstractions
- Microsoft.AspNetCore.Mvc.Analyzers
- Microsoft.AspNetCore.Mvc.ApiExplorer
- Microsoft.AspNetCore.Mvc.Api.Analyzers
- Microsoft.AspNetCore.Mvc.Core
- Microsoft.AspNetCore.Mvc.Cors
- Microsoft.AspNetCore.Mvc.DataAnnotations
- Microsoft.AspNetCore.Mvc.Formatters.Json
- Microsoft.AspNetCore.Mvc.Formatters.Xml
- Microsoft.AspNetCore.Mvc.Localization
- Microsoft.AspNetCore.Mvc.Razor
- Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
- Microsoft.AspNetCore.Mvc.RazorPages
- Microsoft.AspNetCore.Mvc.TagHelpers
- Microsoft.AspNetCore.Mvc.ViewFeatures
- Microsoft.AspNetCore.Razor
- Microsoft.AspNetCore.Razor.Runtime
- Microsoft.AspNetCore.Razor.Design
- Microsoft.AspNetCore.ResponseCaching
- Microsoft.AspNetCore.ResponseCaching.Abstractions
- Microsoft.AspNetCore.ResponseCompression
- Microsoft.AspNetCore.Rewrite
- Microsoft.AspNetCore.Routing
- Microsoft.AspNetCore.Routing.Abstractions
- Microsoft.AspNetCore.Server.HttpSys
- Microsoft.AspNetCore.Server.IIS
- Microsoft.AspNetCore.Server.IISIntegration
- Microsoft.AspNetCore.Server.Kestrel
- Microsoft.AspNetCore.Server.Kestrel.Core
- Microsoft.AspNetCore.Server.Kestrel.Https
- Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
- Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
- Microsoft.AspNetCore.Session
- Microsoft.AspNetCore.SignalR
- Microsoft.AspNetCore.SignalR.Core
- Microsoft.AspNetCore.StaticFiles
- Microsoft.AspNetCore.WebSockets
- Microsoft.AspNetCore.WebUtilities
- Microsoft.Net.Http.Headers
호환성이 손상되는 변경 검토
프레임워크 참조
위에 나열된 패키지 중 하나를 통해 사용할 수 있었던 ASP.NET Core의 기능은 Microsoft.AspNetCore.App
공유 프레임워크의 일부로 사용할 수 있습니다. 공유 프레임워크는 머신에 설치된 어셈블리(.dll 파일) 세트이며 런타임 구성 요소 및 타기팅 팩을 포함합니다. 자세한 내용은 공유 프레임워크를 참조하세요.
Microsoft.NET.Sdk.Web
SDK를 대상으로 하는 프로젝트는Microsoft.AspNetCore.App
프레임워크를 암시적으로 참조합니다.이러한 프로젝트에는 추가 참조가 필요하지 않습니다.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> ... </Project>
Microsoft.NET.Sdk
또는Microsoft.NET.Sdk.Razor
SDK를 대상으로 하는 프로젝트는Microsoft.AspNetCore.App
에 명시적FrameworkReference
를 추가해야 합니다.<Project Sdk="Microsoft.NET.Sdk.Razor"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> <ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> </ItemGroup> ... </Project>
Docker를 사용하는 프레임워크 종속 빌드
ASP.NET Core 공유 프레임워크에 종속되는 패키지를 사용하는 콘솔 앱의 프레임워크 종속 빌드는 다음과 같은 런타임 오류를 발생시킬 수 있습니다.
It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
- No frameworks were found.
Microsoft.AspNetCore.App
는 ASP.NET Core 런타임을 포함하는 공유 프레임워크이며 Docker 이미지에 dotnet/core/aspnet
만 존재합니다. 3.0 SDK는 공유 프레임워크에 있는 라이브러리의 중복 사본을 포함하지 않음으로써 ASP.NET Core를 사용하는 프레임워크 종속 빌드의 크기를 줄입니다. 이를 통해 최대 18MB를 절약할 수 있지만, ASP.NET Core 런타임이 앱을 실행할 수 있도록 설치되어 있어야 합니다.
앱에 ASP.NET Core 공유 프레임워크에 대한 종속성(직접 또는 간접)이 있는지 확인하려면 앱 빌드/게시 중에 생성된 파일을 검사 runtimeconfig.json
합니다. 다음 JSON 파일은 ASP.NET Core 공유 프레임워크에 대한 종속성을 보여 줍니다.
{
"runtimeOptions": {
"tfm": "netcoreapp3.0",
"framework": {
"name": "Microsoft.AspNetCore.App",
"version": "3.0.0"
},
"configProperties": {
"System.GC.Server": true
}
}
}
앱이 Docker를 사용하는 경우, ASP.NET Core 3.0을 포함하는 기본 이미지를 사용합니다. 예들 들어 docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0
입니다.
제거된 어셈블리에 대해 패키지 참조 추가
ASP.NET Core 3.0은 기존에 Microsoft.AspNetCore.App
패키지 참조의 일부였던 일부 어셈블리를 제거합니다. 어느 어셈블리가 제거되었는지 시각화하여 보려면 두 공유 프레임워크 폴더를 비교합니다. 예를 들어, 버전 2.2.7과 3.0.0을 비교합니다.
제거된 어셈블리에서 제공하는 기능을 계속 사용하려면 대응하는 패키지의 3.0 버전을 참조합니다.
개별 사용자 계정을 갖는 템플릿 생성 웹앱의 경우 다음 패키지를 추가해야 합니다.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <UserSecretsId>My-secret</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" /> </ItemGroup> </Project>
-
데이터베이스 공급자별 패키지를 참조하는 방법은 데이터베이스 공급자를 참조하세요.
Identity UI
Identity UI에 대한 지원은 Microsoft.AspNetCore.Identity.UI 패키지를 참조하여 추가할 수 있습니다.
SPA 서비스
인증: 타사 인증 흐름에 대한 지원은 NuGet 패키지를 통해 사용할 수 있습니다.
- Facebook OAuth(Microsoft.AspNetCore.Authentication.Facebook)
- Google OAuth(Microsoft.AspNetCore.Authentication.Google)
- Microsoft Account 인증(Microsoft.AspNetCore.Authentication.MicrosoftAccount)
- OpenID Connect 인증(Microsoft.AspNetCore.Authentication.OpenIdConnect)
- OpenID Connect 전달자 토큰(Microsoft.AspNetCore.Authentication.JwtBearer)
- Twitter OAuth(Microsoft.AspNetCore.Authentication.Twitter)
- WsFederation 인증(Microsoft.AspNetCore.Authentication.WsFederation)
System.Net.HttpClient
에 대한 형식 지정 및 콘텐츠 협상 지원: Microsoft.AspNet.WebApi.Client NuGet 패키지는ReadAsAsync
,PostJsonAsync
와 같은 API를 통해System.Net.HttpClient
에 유용한 확장성을 제공합니다. 그러나 이 패키지는Newtonsoft.Json
System.Text.Json
. 예를 들어 (System.Text.Json
)로 지정된JsonPropertyNameAttribute
serialization 속성 이름은 무시됩니다. 유사한 확장 메서드를 포함하지만 System.Net.Http.Json을 사용하는System.Text.Json
최신 NuGet 패키지가 있습니다.Razor 런타임 컴파일: Razor 보기 및 페이지의 런타임 컴파일 지원은 이제 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation의 일부로 제공됩니다.
MVC
Newtonsoft.Json
(Json.NET) 지원:Newtonsoft.Json
으로 MVC 사용을 위한 지원은 이제Microsoft.AspNetCore.Mvc.NewtonsoftJson
의 일부로 제공됩니다.
시작 변경
다음 이미지는 ASP.NET Core 2.2 Razor Pages 웹앱의 삭제된 줄과 변경된 줄을 보여 줍니다.
위 이미지에서 삭제된 코드는 빨간색으로 표시되어 있습니다. 삭제된 코드는 파일 비교 전에 삭제된 cookie 옵션 코드를 표시하지 않습니다.
다음 이미지는 ASP.NET Core 3.0 Razor Pages 웹앱의 추가된 줄과 변경된 줄을 보여 줍니다.
위 이미지에서 추가된 코드는 녹색으로 표시되어 있습니다. 다음과 같은 변경에 대한 자세한 내용은:
services.AddMvc
에서services.AddRazorPages
로: 본 문서의 MVC 서비스 등록을 참조하세요.CompatibilityVersion
의 경우, ASP.NET Core MVC에 대한 호환성 버전을 참조하세요.IHostingEnvironment
에서IWebHostEnvironment
로: GitHub 공지를 참조하세요.app.UseAuthorization
은 순서 권한 부여 미들웨어를 추가해야 한다는 사실을 보여 주기 위해 템플릿에 추가되었습니다. 앱이 권한 부여를 사용하지 않는 경우app.UseAuthorization
에 대한 호출을 제거할 수 있습니다.app.UseEndpoints
: 본 문서의 Razor Pages 또는 Startup.Configure 마이그레이션을 참조하세요.
분석기 지원
Microsoft.NET.Sdk.Web
을 대상으로 하는 프로젝트는 기존에 Microsoft.AspNetCore.Mvc.Analyzers 패키지의 일부로 제공되었던 분석기를 명시적으로 참조합니다. 이러한 분석기를 참조하기 위해 추가 참조가 필요하지 않습니다.
앱이 기존에 Microsoft.AspNetCore.Mvc.Api.Analyzers 패키지의 일부로 제공되었던 API 분석기를 사용하는 경우, 프로젝트 파일이 .NET Core Web SDK의 일부로 제공되는 분석기를 참조하도록 편집하세요.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
</PropertyGroup>
...
</Project>
Razor 클래스 라이브러리
Razor MVC에 대한 UI 구성 요소를 제공하는 클래스 라이브러리 프로젝트는 프로젝트 파일에서 속성을 설정 AddRazorSupportForMvc
해야 합니다.
<PropertyGroup>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
In-process 호스팅 모델
ASP.NET Core 3.0 이상에서, 프로젝트는 기본적으로 In-Process 호스팅 모델로 설정됩니다. <AspNetCoreHostingModel>
속성의 값이 InProcess
인 경우 선택적으로 프로젝트 파일에서 이 속성을 제거할 수 있습니다.
Kestrel
구성
(에서 제공하는 웹 호스트 작성기)로 ConfigureWebHostDefaults
Program.cs
구성을 마이그레이션 Kestrel 합니다.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(serverOptions =>
{
// Set properties and call methods on options
})
.UseStartup<Startup>();
});
앱이 ConfigureWebHostDefaults
대신 ConfigureWebHost
를 사용하여 수동으로 호스트를 만드는 경우, 웹 호스트 작성기에서 UseKestrel
을 호출합니다.
public static void Main(string[] args)
{
var host = new HostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureWebHost(webBuilder =>
{
webBuilder.UseKestrel(serverOptions =>
{
// Set properties and call methods on options
})
.UseIISIntegration()
.UseStartup<Startup>();
})
.Build();
host.Run();
}
연결 미들웨어가 연결 어댑터를 대체함
Kestrel에서 연결 어댑터(Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter
)가 제거되었습니다. 연결 어댑터를 연결 미들웨어로 대체하세요. 연결 미들웨어는 ASP.NET Core 파이프라인의 HTTP 미들웨어와 비슷하나 하위 수준 연결을 위한 것입니다. HTTPS 및 연결 로깅:
- 연결 어댑터에서 연결 미들웨어로 이동되었습니다.
- 이들 확장 메서드는 이전 버전의 ASP.NET Core에서와 동일하게 작동합니다.
자세한 내용은 Kestrel 문서의 ListenOptions.Protocols 섹션의 TlsFilterConnectionHandler 예제를 참조하세요.
전송 추상화가 이동되고 퍼블릭으로 변경됨
Kestrel 전송 계층이 Connections.Abstractions
에서 공용 인터페이스로 공개되었습니다. 이 업데이트의 일환으로:
Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
및 관련 형식이 제거되었습니다.- NoDelay가 ListenOptions에서 전송 옵션으로 이동되었습니다.
Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode
가 KestrelServerOptions에서 제거되었습니다.
자세한 내용은 다음 GitHub 리소스를 참조하세요.
- Client/server networking abstractions(클라이언트/서버 네트워킹 추상화, dotnet/AspNetCore #10308)
- Implement new bedrock listener abstraction and re-plat Kestrel on top(새 Bedrock 수신기 추상을 구현하고 그 위에 Kestrel re-plat, dotnet/AspNetCore #10321)
Kestrel 요청 후행부 헤더
이전 버전의 ASP.NET Core를 대상으로 하는 앱의 경우:
- Kestrel이 요청 헤더 컬렉션에 HTTP/1.1 청크 분할된 후행부 헤더를 추가합니다.
- 후행부는 요청 본문을 끝까지 읽은 후에 사용 가능합니다.
이로 인해 헤더와 후행부 사이에 모호성이 발생하므로 3.0에서는 후행부가 새 컬렉션(RequestTrailerExtensions
)으로 이동되었습니다.
HTTP/2 요청 후행부는:
- ASP.NET Core 2.2에서 사용할 수 없습니다.
- 3.0에서
RequestTrailerExtensions
로 사용할 수 있습니다.
이러한 후행부에 액세스할 수 있도록 새 요청 확장 메서드가 제공됩니다. HTTP/1.1과 마찬가지로, 후행부는 요청 본문을 끝까지 읽은 후에 사용 가능합니다.
3.0 릴리스에서는 다음 RequestTrailerExtensions
메서드를 사용할 수 있습니다.
GetDeclaredTrailers
: Gets 본문 다음에 어느 후행부가 나오는지 나열하는 요청Trailer
헤더를 가져옵니다.SupportsTrailers
: 요청이 수신하는 후행부 헤더를 지원하는지 여부를 나타냅니다.CheckTrailersAvailable
: 요청이 후행부를 지원하는지와 후행부를 읽을 수 있는지 여부를 검사합니다. 이 검사는 읽을 후행부가 있다고 가정하지 않습니다. 이 메서드가true
를 반환하는 경우에도 읽을 후행부가 없을 수 있습니다.GetTrailer
: 응답으로부터 요청된 후행 헤더를 가져옵니다.GetTrailer
를 호출하기 전에SupportsTrailers
를 검사하세요. 그러지 않으면 요청이 후행 헤더를 지원하지 않는 경우 NotSupportedException이 발생할 수 있습니다.
자세한 내용은 Put request trailers in a separate collection(요청 후행부를 별도의 컬렉션에 배치, dotnet/AspNetCore #10410)을 참조하세요.
AllowSynchronousIO가 비활성화됨
AllowSynchronousIO
는 HttpRequest.Body.Read
, HttpResponse.Body.Write
, Stream.Flush
와 같은 동기 I/O API를 사용 또는 사용하지 않음으로 설정합니다. 이러한 API는 스레드 고갈의 원인이 되며 앱 크래시로 이어질 수 있습니다. 3.0에서 AllowSynchronousIO
는 기본적으로 사용하지 않도록 설정됩니다. 자세한 내용은 Kestrel 문서의 동기 I/O 섹션을 참조하세요.
동기 I/O가 필요한 경우, 사용 중인 서버에서 AllowSynchronousIO
옵션을 구성하여 사용하도록 설정할 수 있습니다(예: Kestrel을 사용하는 경우 ConfigureKestrel
을 호출할 때). 서버(Kestrel, HttpSys, TestServer 등)는 다른 서버에 영향을 주지 않는 자체 AllowSynchronousIO
옵션을 갖습니다. 동기 I/O는 IHttpBodyControlFeature.AllowSynchronousIO
옵션을 사용하여 모든 서버에서 요청 건별로 사용하도록 설정할 수 있습니다.
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
TextWriter 구현이나 Dispose에서 동기 API를 호출하는 다른 스트림에 문제가 있는 경우 대신 새 DisposeAsync API를 호출하세요.
자세한 내용은 [Announcement] AllowSynchronousIO disabled in all servers([공지] 모든 서버에서 AllowSynchronousIO가 사용하지 않도록 설정됨, dotnet/AspNetCore #7644)를 참조하세요.
출력 포맷터 버퍼링
Newtonsoft.Json, XmlSerializer 및 DataContractSerializer 기반 출력 포맷터는 동기 직렬화만 지원합니다. 이러한 포맷터가 서버의 AllowSynchronousIO 제한과 함께 작동하도록 하기 위해, MVC는 디스크에 쓰기 전에 이러한 포맷터의 출력을 버퍼링합니다. 버퍼링의 결과로 MVC는 이러한 포맷터를 사용하여 응답할 때 Content-Length 헤더를 포함하게 됩니다.
System.Text.Json은 비동기 직렬화를 지원하며, 따라서 System.Text.Json
기반 포맷터는 버퍼링하지 않습니다. 성능 향상을 위해 이 포맷터를 사용하는 방안을 고려하세요.
버퍼링을 사용하지 않도록 설정하려면 애플리케이션은 시작에서 SuppressOutputFormatterBuffering을 구성할 수 있습니다.
services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)
AllowSynchronousIO
도 구성하지 않을 경우 이로 인해 애플리케이션이 런타임 예외를 throw할 수 있습니다.
Microsoft.AspNetCore.Server.Kestrel.Https 어셈블리가 제거됨
ASP.NET Core 2.1에서 Microsoft.AspNetCore.Server.Kestrel.Https.dll의 콘텐츠가 Microsoft.AspNetCore.Server.Kestrel.Core.dll로 이동되었습니다. 이는 TypeForwardedTo
특성을 사용하는, 호환성을 손상하지 않는 업데이트입니다. 3.0에서는 빈 Microsoft.AspNetCore.Server.Kestrel.Https.dll 어셈블리와 NuGet 패키지가 제거되었습니다.
Microsoft.AspNetCore.Server.Kestrel.Https를 참조하는 라이브러리는 ASP.NET Core 종속성을 2.1 이상으로 업데이트해야 합니다.
ASP.NET Core 2.1 이상을 대상으로 하는 앱 및 라이브러리는 Microsoft.AspNetCore.Server.Kestrel.Https 패키지에 대한 직접 참조를 모두 제거해야 합니다.
Newtonsoft.Json(Json.NET) 지원
ASP.NET Core 공유 프레임워크를 개선하기 위한 노력의 일환으로, ASP.NET Core 공유 프레임워크에서 Newtonsoft.Json(Json.NET)이 제거되었습니다.
이제 ASP.NET Core의 기본 JSON 직렬 변환기는 .NET Core 3.0에 새로 도입된 System.Text.Json입니다. 가능한 경우 System.Text.Json
을 사용하세요. System.Text.Json은 고성능이며 추가 라이브러리 종속성이 필요하지 않습니다. 그러나 System.Text.Json
은 새로 도입되었기 때문에 현재 앱에 필요한 기능이 누락되어 있을 수 있습니다. 자세한 내용은 Newtonsoft.Json에서 System.Text.Json로 마이그레이션하는 방법을 참조하세요.
ASP.NET Core 3.0 SignalR 프로젝트에서 Newtonsoft.Json 사용
Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson NuGet 패키지를 설치합니다.
클라이언트에서
AddNewtonsoftJsonProtocol
메서드 호출을HubConnectionBuilder
인스턴스에 연결합니다.new HubConnectionBuilder() .WithUrl("/chathub") .AddNewtonsoftJsonProtocol(...) .Build();
서버에서
AddNewtonsoftJsonProtocol
메서드 호출을Startup.ConfigureServices
의AddSignalR
메서드 호출에 연결합니다.services.AddSignalR() .AddNewtonsoftJsonProtocol(...);
ASP.NET Core 3.0 MVC 프로젝트에서 Newtonsoft.Json 사용
Microsoft.AspNetCore.Mvc.NewtonsoftJson
패키지를 설치합니다.Startup.ConfigureServices
가AddNewtonsoftJson
을 호출하도록 업데이트합니다.services.AddMvc() .AddNewtonsoftJson();
AddNewtonsoftJson
은 다음과 같은 새 MVC 서비스 등록 메서드와 호환됩니다.AddRazorPages
AddControllersWithViews
AddControllers
services.AddControllers() .AddNewtonsoftJson();
Newtonsoft.Json
설정은AddNewtonsoftJson
에 대한 호출에서 설정할 수 있습니다.services.AddMvc() .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
참고:
AddNewtonsoftJson
메서드를 사용할 수 없는 경우,Microsoft.AspNetCore.Mvc.NewtonsoftJson
패키지를 설치했는지 확인하세요. 종종 실수로Microsoft.AspNetCore.Mvc.NewtonsoftJson
패키지 대신 Newtonsoft.Json 패키지를 설치하는 경우가 있습니다.
자세한 내용은 Newtonsoft.Json 기반 JSON 형식 지원 추가를 참조하세요.
MVC 서비스 등록
ASP.NET Core 3.0에 Startup.ConfigureServices
에서 MVC 시나리오를 등록하기 위한 새로운 옵션이 추가되었습니다.
IServiceCollection
에서 MVC 시나리오와 관련된 세 개의 최상위 수준 확장 메서드를 사용할 수 있습니다. 템플릿은 AddMvc
대신 이러한 새 메서드를 사용합니다. 그러나 AddMvc
는 계속해서 이전 릴리스와 동일하게 동작합니다.
다음 예제에서는 컨트롤러와 API 관련 기능에 대한 지원을 추가합니다(보기 및 페이지에 대한 지원은 추가하지 않음). API 템플릿은 다음 코드를 사용합니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
다음 예제에서는 컨트롤러, API 관련 기능 및 보기에 대한 지원을 추가합니다(페이지에 대한 지원은 추가하지 않음). 웹 애플리케이션(MVC) 템플릿은 다음 코드를 사용합니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
다음 예제에서는 Razor Pages에 대한 지원과 최소한의 컨트롤러 지원을 추가합니다. 웹 애플리케이션 템플릿은 다음 코드를 사용합니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
새 메서드를 결합하는 것도 가능합니다. 다음 예제는 ASP.NET Core 2.2에서 AddMvc
를 호출하는 것과 동일합니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
라우팅 시작 코드
앱이 UseMvc
또는 UseSignalR
을 호출한다면 가능한 경우 앱을 엔드포인트 라우팅으로 마이그레이션하세요. 이전 버전의 MVC와의 엔드포인트 라우팅 호환성을 개선하기 위해, ASP.NET Core 2.2에 도입되었던 URL 생성 변경 사항의 일부가 복원되었습니다. 2.2에서 엔드포인트 라우팅을 사용하는 데 문제가 있었다면 ASP.NET Core 3.0에서는 이러한 문제가 개선되었을 것입니다. 단, 다음과 같은 예외가 있습니다.
- 앱이
IRouter
를 구현하거나Route
에서 상속받는 경우 DynamicRouteValuesTransformer를 대체로 사용하세요. - 앱이 MVC 안에서
RouteData.Routers
에 직접 액세스하여 URL을 구문 분석하는 경우 LinkParser.ParsePathByEndpointName을 사용하여 대체할 수 있습니다.- 경로 이름을 사용하여 경로를 정의합니다.
LinkParser.ParsePathByEndpointName
을 사용하여 원하는 경로 이름을 전달합니다.
엔드포인트 라우팅은 IRouter
와 동일한 경로 패턴 구문과 경로 패턴 작성 기능을 지원합니다. 엔드포인트 라우팅은 IRouteConstraint
를 지원합니다. 엔드포인트 라우팅은 [Route]
, [HttpGet]
및 기타 MVC 라우팅 특성을 지원합니다.
대부분의 애플리케이션에서는 Startup
만 변경하면 됩니다.
Startup.Configure 마이그레이션
일반적인 조언:
UseRouting
를 추가합니다.앱이
UseStaticFiles
를 호출하는 경우UseRouting
앞에UseStaticFiles
를 배치합니다.앱이
AuthorizePage
나[Authorize]
와 같은 인증/권한 부여 기능을 사용하는 경우 호출을UseAuthentication
과UseAuthorization
에서UseRouting
및UseCors
뒤에UseEndpoints
앞에 배치합니다.public void Configure(IApplicationBuilder app) { ... app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
UseMvc
또는UseSignalR
을UseEndpoints
로 대체합니다.앱이
[EnableCors]
와 같은 CORS 시나리오를 사용하는 경우 CORS를 사용하는 다른 모든 미들웨어 앞에UseCors
에 대한 호출을 배치합니다(예:UseCors
를UseAuthentication
,UseAuthorization
,UseEndpoints
앞에 배치).IHostingEnvironment
를IWebHostEnvironment
로 대체하고 Microsoft.AspNetCore.Hosting 네임스페이스에 대한using
문을 추가합니다.IApplicationLifetime
을 IHostApplicationLifetime으로 대체합니다(Microsoft.Extensions.Hosting 네임스페이스).EnvironmentName
을 Environments으로 대체합니다(Microsoft.Extensions.Hosting 네임스페이스).
다음 코드는 일반적인 ASP.NET Core 2.2 앱의 Startup.Configure
의 예시입니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseStaticFiles();
app.UseAuthentication();
app.UseSignalR(hubs =>
{
hubs.MapHub<ChatHub>("/chat");
});
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
이전 Startup.Configure
코드를 업데이트한 후에:
public void Configure(IApplicationBuilder app)
{
...
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chat");
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
Warning
대부분의 앱에서 UseAuthentication
, UseAuthorization
, UseCors
에 대한 호출이 효력을 가지려면 UseRouting
에 대한 호출과 UseEndpoints
에 대한 호출 사이에 와야 합니다.
상태 검사
상태 검사는 제네릭 호스트와의 엔드포인트 라우팅을 사용합니다. Startup.Configure
에서 엔드포인트 URL 또는 상대 경로를 사용하여 엔드포인트 작성기에 MapHealthChecks
를 호출합니다.
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
상태 검사 엔드포인트는 다음을 수행할 수 있습니다.
- 허용되는 호스트/포트를 하나 이상 지정합니다.
- 권한 부여가 필요합니다.
- CORS가 필요합니다.
자세한 내용은 ASP.NET Core의 상태 검사을 참조하세요.
보안 미들웨어 지침
권한 부여 및 CORS에 대한 지원이 미들웨어 접근 방식을 중심으로 통합되었습니다. 이에 따라 이러한 시나리오에서 동일한 미들웨어와 기능을 사용할 수 있게 되었습니다. 이번 릴리스에서는 업데이트된 권한 부여 미들웨어가 제공되었으며, CORS 미들웨어는 MVC 컨트롤러가 사용하는 특성을 이해할 수 있도록 개선되었습니다.
CORS
이전에는 CORS를 구성하는 작업이 쉽지 않았습니다. 일부 사용 사례에서 사용할 수 있는 미들웨어가 제공되긴 했지만, 그 밖의 사용 사례에서는 미들웨어 없이 MVC 필터를 사용해야 했습니다. ASP.NET Core 3.0에서는 CORS가 필요한 모든 앱이 CORS 미들웨어를 엔드포인트 라우팅과 함께 사용해야 합니다. UseCors
는 기본 정책을 사용하여 제공할 수 있으며, 필요한 경우 [EnableCors]
및 [DisableCors]
특성을 사용하여 기본 정책을 재정의할 수 있습니다.
다음 예제에서
- CORS는
default
명명된 정책을 갖는 모든 엔드포인트에서 사용하도록 설정됩니다. MyController
클래스는[DisableCors]
특성을 사용하여 CORS를 사용하지 않도록 설정합니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseCors("default");
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
[DisableCors]
public class MyController : ControllerBase
{
...
}
Authorization
이전 버전의 ASP.NET Core에서는 권한 부여 지원이 [Authorize]
특성을 통해 제공되었습니다. 권한 부여 미들웨어는 없었습니다. ASP.NET Core 3.0에서는 권한 부여 미들웨어가 요구됩니다. ASP.NET Core 권한 부여 미들웨어(UseAuthorization
)를 UseAuthentication
직후에 배치하는 것을 권장합니다. 권한 부여 미들웨어는 기본 정책을 사용하여 구성할 수도 있으며, 기본 정책은 재정의할 수 있습니다.
ASP.NET Core 3.0 이상에서는 UseAuthorization
이 Startup.Configure
에서 호출됩니다. 아래의 HomeController
에서는 로그인한 사용자가 필요합니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
public class HomeController : Controller
{
[Authorize]
public IActionResult BuyWidgets()
{
...
}
}
엔드포인트 라우팅을 사용할 때는 AuthorizeFilter를 사용하지 말고 권한 부여 미들웨어를 사용하시기 바랍니다. 앱이 AuthorizeFilter
를 MVC의 전역 필터로 사용하는 경우, 코드가 AddAuthorization
에 대한 호출에서 정책을 제공하도록 리팩터링하는 것을 권장합니다.
DefaultPolicy
는 인증을 요구하도록 초기 구성되므로 추가 구성이 필요하지 않습니다. 다음 예제에서는 MVC 엔드포인트가 RequireAuthorization
으로 표시되어 있으므로 모든 요청이 DefaultPolicy
에 따라 권한 부여되어야 합니다. 그러나 HomeController
에는 [AllowAnonymous]
가 있기 때문에 사용자가 앱에 로그인하지 않아도 액세스를 허용합니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization();
});
}
[AllowAnonymous]
public class HomeController : Controller
{
...
}
특정 엔드포인트의 권한 부여
특정 엔드포인트 클래스에 대해서도 권한 부여를 구성할 수 있습니다. 다음 코드는 전역 AuthorizeFilter
를 구성한 MVC 앱을 권한 부여가 필요한 특정 정책을 갖는 앱으로 변환하는 예입니다.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
static readonly string _RequireAuthenticatedUserPolicy =
"RequireAuthenticatedUserPolicy";
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
// Pre 3.0:
// services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(...));
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(o => o.AddPolicy(_RequireAuthenticatedUserPolicy,
builder => builder.RequireAuthenticatedUser()));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute()
.RequireAuthorization(_RequireAuthenticatedUserPolicy);
endpoints.MapRazorPages();
});
}
}
정책을 사용자 지정하는 것도 가능합니다. DefaultPolicy
는 인증을 요구하도록 구성되었습니다.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization();
endpoints.MapRazorPages();
});
}
}
[AllowAnonymous]
public class HomeController : Controller
{
또는 FallbackPolicy
를 구성하여 [Authorize]
또는 RequireAuthorization
없이도 권한 부여를 요구하도록 모든 엔드포인트를 구성할 수도 있습니다. FallbackPolicy
는 DefaultPolicy
와 다릅니다. DefaultPolicy
는 [Authorize]
또는 RequireAuthorization
에 의해 트리거되는 반면 FallbackPolicy
는 설정된 다른 정책이 없는 경우에 트리거됩니다. FallbackPolicy
는 권한 부여 없이 요청을 허용하도록 초기 구성됩니다.
다음 예제는 위의 DefaultPolicy
예제와 동일하나, [AllowAnonymous]
가 지정된 경우를 제외하고 항상 모든 엔드포인트에서 인증을 요구하도록 FallbackPolicy
를 사용합니다.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
[AllowAnonymous]
public class HomeController : Controller
{
...
}
미들웨어에 의한 권한 부여는 프레임워크에 권한 부여에 대한 구체적인 지식이 없는 상태로 작동합니다. 예를 들어, 상태 검사는 권한 부여에 대한 구체적인 지식이 없지만 미들웨어에 의해 적용된 구성 가능한 권한 부여 정책을 가질 수 있습니다.
이에 더해, 각 엔드포인트는 자체 권한 부여 요구 사항을 사용자 지정할 수 있습니다. 다음 예제에서 UseAuthorization
은 DefaultPolicy
를 사용하여 권한 부여를 처리하는 반면 /healthz
상태 검사 엔드포인트에는 admin
사용자가 필요합니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints
.MapHealthChecks("/healthz")
.RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
});
}
일부 시나리오에서는 보호가 구현됩니다. 엔드포인트 미들웨어는 미들웨어가 누락되어 권한 부여 또는 CORS 정책을 건너뛴 경우 예외를 throw합니다. 잘못된 구성에 대한 추가 피드백을 제공하기 위한 분석기 지원은 현재 구현 중입니다.
사용자 지정 권한 부여 처리기
앱이 사용자 지정 권한 부여 처리기를 사용하는 경우, 엔드포인트 라우팅은 처리기에 MVC와 다른 리소스 유형을 전달합니다. 권한 부여 처리기 컨텍스트 리소스의 형식이 AuthorizationFilterContext(MVC 필터가 제공하는 리소스 형식)여야 하는 처리기는 RouteEndpoint 리소스 형식(엔드포인트 라우팅이 권한 부여 처리기에 제공하는 리소스 형식)을 처리하도록 업데이트해야 합니다.
MVC는 여전히 AuthorizationFilterContext
리소스를 사용하므로, 앱이 엔드포인트 라우팅 권한 부여와 함께 MVC 권한 부여 필터를 사용하는 경우 두 가지 리소스 형식을 처리해야 할 수 있습니다.
SignalR
SignalR 허브의 매핑은 이제 UseEndpoints
에서 이루어집니다.
각 허브를 MapHub
를 사용하여 매핑하세요. 이전 버전에서와 마찬가지로, 각 허브는 명시적으로 나열됩니다.
다음 예제에서는 ChatHub
SignalR 허브에 대한 지원이 추가됩니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>();
});
}
클라이언트에서 메시지 크기 제한을 제어하기 위한 새로운 옵션이 있습니다. 예를 들어 Startup.ConfigureServices
에 만듭니다.
services.AddSignalR(hubOptions =>
{
hubOptions.MaximumReceiveMessageSize = 32768;
});
ASP.NET Core 2.2에서는 TransportMaxBufferSize
를 설정하여 최대 메시지 크기를 제어할 수 있었습니다. ASP.NET Core 3.0에서 이 옵션은 역 압력이 관찰되기 전에만 최대 크기를 제어합니다.
SignalR 공유 프레임워크의 어셈블리
ASP.NET Core SignalR 서버 쪽 어셈블리는 이제 .NET Core SDK와 함께 설치됩니다. 자세한 내용은 이 문서에서 사용되지 않는 패키지 참조 제거를 참조하세요.
MVC 컨트롤러
컨트롤러의 매핑은 이제 UseEndpoints
에서 이루어집니다.
앱이 특성 라우팅을 사용하는 경우 MapControllers
를 추가하세요. 라우팅은 ASP.NET Core 3.0 이상의 여러 프레임워크에 대한 지원을 포함하므로, 특성으로 라우팅되는 컨트롤러를 추가하는 것은 선택 사항입니다.
다음 내용을
MapRoute
(MapControllerRoute
사용)MapAreaRoute
(MapAreaControllerRoute
사용)
이제 라우팅은 MVC 외의 여러 프레임워크에 대한 지원을 포함하므로, 이러한 메서드가 하는 일을 명확히 알 수 있도록 용어가 변경되었습니다. MapControllerRoute
/MapAreaControllerRoute
/MapDefaultControllerRoute
와 같은 규칙 기반 경로는 추가된 순서대로 적용됩니다. 보다 구체적인 경로(예: 영역에 대한 경로)를 먼저 배치하세요.
다음 예제에서
MapControllers
는 특성으로 라우팅되는 컨트롤러에 대한 지원을 추가합니다.MapAreaControllerRoute
는 한 영역에 있는 컨트롤러에 대한 규칙 기반 경로를 추가합니다.MapControllerRoute
는 컨트롤러에 대한 규칙 기반 경로를 추가합니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapAreaControllerRoute(
"admin",
"admin",
"Admin/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
"default", "{controller=Home}/{action=Index}/{id?}");
});
}
컨트롤러 작업 이름에서 비동기 접미사 제거
ASP.NET Core 3.0에서, ASP.NET Core MVC의 컨트롤러 작업 이름에서 Async
접미사가 제거되었습니다. 이 새로운 기본값은 라우팅 및 링크 생성에 영향을 줍니다. 예시:
public class ProductsController : Controller
{
public async Task<IActionResult> ListAsync()
{
var model = await _dbContext.Products.ToListAsync();
return View(model);
}
}
ASP.NET Core 3.0 이전:
위 작업은 Products/ListAsync 경로에서 액세스할 수 있었습니다.
링크를 생성하려면
Async
접미사를 지정해야 했습니다. 예시:<a asp-controller="Products" asp-action="ListAsync">List</a>
ASP.NET Core 3.0:
위 작업은 Products/List 경로에서 액세스할 수 있습니다.
링크 생성을 위해
Async
접미사를 지정할 필요가 없습니다. 예시:<a asp-controller="Products" asp-action="List">List</a>
이 변경은 [ActionName]
특성을 사용하여 지정된 이름에는 영향을 주지 않습니다. 기본 동작은 Startup.ConfigureServices
에서 다음 코드를 사용하여 사용하지 않도록 설정할 수 있습니다.
services.AddMvc(options =>
options.SuppressAsyncSuffixInActionNames = false);
링크 생성 변경 사항
링크 생성에는 몇 가지 차이점이 있습니다(예: Url.Link
및 유사한 API 사용). 여기에는 다음이 포함됩니다.
- 기본적으로, 엔드포인트 라우팅을 사용할 때는 생성된 URI의 경로 매개 변수의 대소문자 구분이 보존되지 않을 수 있습니다. 이 동작은
IOutboundParameterTransformer
인터페이스를 통해 제어할 수 있습니다. - 유효하지 않은 경로(존재하지 않는 컨트롤러/작업 또는 페이지)에 대해 URI를 생성하면 유효하지 않은 URI가 생성되는 대신 엔드포인트 라우팅 아래에 빈 문자열이 생성됩니다.
- 앰비언트 값(현재 컨텍스트의 경로 매개 변수)는 엔드포인트 라우팅을 사용하는 링크 생성에서 자동으로 사용되지 않습니다. 기존에는 다른 작업(또는 페이지)로의 링크를 생성할 때 ‘현재’ 경로 앰비언트 값으로부터 지정되지 않은 경로 값이 유추되었습니다. 엔드포인트 라우팅을 사용할 때는 링크 생성 중에 모든 경로 매개 변수를 명시적으로 지정해야 합니다.
Razor Pages
Razor Pages의 매핑은 이제 UseEndpoints
에서 이루어집니다.
앱이 Razor Pages를 사용하는 경우 MapRazorPages
를 추가하세요. 엔드포인트 라우팅은 여러 프레임워크에 대한 지원을 포함하므로 이제 Razor Pages를 추가하는 것은 선택 사항입니다.
다음 Startup.Configure
메서드에서 MapRazorPages
는 Razor Pages에 대한 지원을 추가합니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
엔드포인트 라우팅 없이 MVC 사용
ASP.NET Core 3.0에서 UseMvc
또는 UseMvcWithDefaultRoute
를 통해 MVC를 사용하려면 Startup.ConfigureServices
내에서 명시적으로 옵트인해야 합니다. 이는 MVC가 초기화 중에 권한 부여 및 CORS 미들웨어를 사용할 수 있는지 여부를 알아야 하기 때문에 요구됩니다. 앱이 지원되지 않는 구성을 사용하려고 시도하는 경우 경고를 발생시키는 분석기가 제공됩니다.
앱에 레거시 IRouter
지원이 필요한 경우, Startup.ConfigureServices
에서 다음 방법 중 하나를 사용하여 EnableEndpointRouting
을 사용하지 않도록 설정하세요.
services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddControllers(options => options.EnableEndpointRouting = false);
services.AddControllersWithViews(options => options.EnableEndpointRouting = false);
services.AddRazorPages().AddMvcOptions(options => options.EnableEndpointRouting = false);
상태 검사
상태 검사는 엔드포인트 라우팅과 함께 ‘라우터웨어’로 사용할 수 있습니다.
엔드포인트 라우팅과 함께 상태 검사를 사용하려면 MapHealthChecks
를 추가하세요. MapHealthChecks
메서드는 UseHealthChecks
와 비슷한 인수를 받습니다. UseHealthChecks
대신 MapHealthChecks
를 사용하면 권한 부여를 적용할 수 있고 매칭 정책을 보다 세밀하게 제어할 수 있다는 이점이 있습니다.
다음 예제에서, /healthz
에서의 상태 검사 엔드포인트에 MapHealthChecks
가 호출됩니다.
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
});
}
HostBuilder가 WebHostBuilder를 대체함
ASP.NET Core 3.0 템플릿은 제네릭 호스트를 사용합니다. 이전 버전에서는 웹 호스트를 사용했습니다. 다음 코드는 ASP.NET Core 3.0 템플릿에서 생성된 Program
클래스를 보여 줍니다.
// requires using Microsoft.AspNetCore.Hosting;
// requires using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
다음 코드는 ASP.NET Core 2.2 템플릿에서 생성된 Program
클래스를 보여 줍니다.
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
IWebHostBuilder는 3.0에도 남아 있으며, 위의 코드 샘플에서 볼 수 있는 webBuilder
의 형식입니다. WebHostBuilder는 이후 릴리스에서 더 이상 사용되지 않고 HostBuilder
로 대체됩니다.
WebHostBuilder
에서 HostBuilder
로 변경됨에 따라 주목해야 할 가장 큰 차이는 DI(종속성 삽입)입니다. HostBuilder
를 사용할 때는 Startup
의 생성자에 다음 항목만 삽입할 수 있습니다.
HostBuilder
DI는 제한 사항은:
- DI 컨테이너가 한 번만 빌드되도록 합니다.
- 여러 인스턴스의 싱글톤 확인과 같은 결과 개체 수명 문제를 방지합니다.
자세한 내용은 Avoiding Startup service injection in ASP.NET Core 3(ASP.NET Core 3에서 시작 서비스 삽입 방지)을 참조하세요.
AddAuthorization이 다른 어셈블리로 이동됨
Microsoft.AspNetCore.Authorization.dll의 ASP.NET Core 2.2 이하 AddAuthorization
메서드는:
AddAuthorizationCore
로 이름이 변경되었습니다.- Microsoft.AspNetCore.Authorization.Policy.dll로 이동되었습니다.
Microsoft.AspNetCore.Authorization.dll과 Microsoft.AspNetCore.Authorization.Policy.dll을 모두 사용하는 앱은 영향을 받지 않습니다.
Microsoft.AspNetCore.Authorization.Policy.dll을 사용하지 않는 앱은 다음 중 하나를 수행해야 합니다.
- Microsoft.AspNetCore.Authorization.Policy.dll에 대한 참조를 추가합니다. 이 방법은 대부분의 앱에서 작동하며, 요구되는 유일한 작업입니다.
AddAuthorizationCore
사용으로 전환합니다.
자세한 내용은 Breaking change in AddAuthorization(o =>
) overload lives in a different assembly #386(AddAuthorization(o =>) 오버로드의 호환성이 손상되는 변경이 다른 어셈블리에 있음 #386)을 참조하세요.
Identity UI
ASP.NET Core 3.0의 Identity UI 업데이트:
- Microsoft.AspNetCore.Identity.UI에 대한 패키지 참조를 추가합니다.
- Razor Pages를 사용하지 않는 앱은
MapRazorPages
를 호출해야 합니다. 본 문서의 Razor Pages를 참조하세요. - 부트스트랩 4가 기본 UI 프레임워크입니다. 기본값을 변경하려면
IdentityUIFrameworkVersion
프로젝트 속성을 설정하세요. 자세한 내용은 GitHub 공지를 참조하세요.
SignalR
SignalR JavaScript 클라이언트가 @aspnet/signalr
에서 @microsoft/signalr
로 변경되었습니다. 이 변경에 대응하려면 파일, require
문 및 ECMAScript import
문의 참조 package.json
를 변경합니다.
System.Text.Json이 기본 프로토콜임
이제 System.Text.Json
이 클라이언트와 서버가 사용하는 기본 허브 프로토콜입니다.
Startup.ConfigureServices
에서 AddJsonProtocol
을 호출하여 직렬 변환기 옵션을 설정합니다.
서버:
services.AddSignalR(...)
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.WriteIndented = false;
})
클라이언트:
new HubConnectionBuilder()
.WithUrl("/chathub")
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.WriteIndented = false;
})
.Build();
Newtonsoft.Json으로 전환
System.Text.Json에서 지원되지 않는 Newtonsoft.Json의 기능을 사용하는 경우, Newtonsoft.Json
으로 다시 전환할 수 있습니다. 본 문서의 ASP.NET Core 3.0 SignalR 프로젝트에서 Newtonsoft.Json 사용을 참조하세요.
Redis 분산 캐시
ASP.NET Core 3.0 이상 앱에서는 Microsoft.Extensions.Caching.Redis 패키지를 사용할 수 없습니다. 패키지 참조를 Microsoft.Extensions.Caching.StackExchangeRedis로 대체하세요. 자세한 내용은 ASP.NET Core의 분산 캐싱을 참조하세요.
런타임 컴파일에 옵트인
ASP.NET Core 3.0 이전에는 보기의 런타임 컴파일이 프레임워크의 암시적 기능이었습니다. 런타임 컴파일은 보기의 빌드 시간 컴파일을 보완합니다. 전체 앱을 다시 빌드 Razor 하지 않고도 파일이 수정될 때 프레임워크에서 보기 및 페이지(.cshtml
파일)를 컴파일할 수 있습니다. 이 기능은 IDE에서 빠른 편집을 적용하고 브라우저를 새로 고침하여 변경 내용을 확인하는 시나리오를 지원합니다.
ASP.NET Core 3.0에서는 런타임 컴파일이 옵트인 시나리오가 되었습니다. 빌드 시간 컴파일은 보기 컴파일에 대해 기본적으로 설정되는 유일한 메커니즘입니다. 런타임은 Visual Studio Code의 Visual Studio 또는 dotnet-watch 를 사용하여 파일의 변경 내용을 .cshtml
감지할 때 프로젝트를 다시 빌드합니다. Visual Studio에서 실행 중인 프로젝트의 파일(Ctrl+F5)을 변경 .cshtml
.razor
.cs
하지만 디버그되지 않음(F5)은 프로젝트의 다시 컴파일을 트리거합니다.
ASP.NET Core 3.0 프로젝트에서 런타임 컴파일을 사용하도록 설정하려면:
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation NuGet 패키지를 설치합니다.
Startup.ConfigureServices
가AddRazorRuntimeCompilation
을 호출하도록 업데이트합니다.ASP.NET Core MVC에서는 다음 코드를 사용합니다.
services.AddControllersWithViews() .AddRazorRuntimeCompilation(...);
ASP.NET Core Razor Pages에서는 다음 코드를 사용합니다.
services.AddRazorPages() .AddRazorRuntimeCompilation(...);
https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation의 샘플은 개발 환경에서 조건부로 런타임 컴파일을 사용하도록 설정하는 예제를 보여 줍니다.
Razor 파일 컴파일에 대한 자세한 내용은 ASP.NET Core Razor에서 파일 컴파일을 참조하세요.
다중 대상 지정을 통해 라이브러리 마이그레이션
라이브러리가 ASP.NET Core의 여러 버전을 지원해야 하는 경우가 있습니다. 이전 버전의 ASP.NET Core에 대해 컴파일된 대부분의 라이브러리는 계속해서 문제없이 작동할 것입니다. 아래와 같은 조건에서는 앱을 교차 컴파일해야 합니다.
- 라이브러리가 이진 호환성을 손상하는 변경이 있는 기능을 사용합니다.
- 라이브러리가 ASP.NET Core 3.0의 새로운 기능을 사용해야 합니다.
예시:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
</ItemGroup>
</Project>
#ifdefs
를 사용하여 ASP.NET Core 3.0 API를 사용하도록 설정합니다.
var webRootFileProvider =
#if NETCOREAPP3_0
GetRequiredService<IWebHostEnvironment>().WebRootFileProvider;
#elif NETSTANDARD2_0
GetRequiredService<IHostingEnvironment>().WebRootFileProvider;
#else
#error unknown target framework
#endif
클래스 라이브러리에서 ASP.NET Core API를 사용하는 방법에 대한 자세한 내용은 클래스 라이브러리에서 ASP.NET Core API 사용을 참조하세요.
기타 변경 내용
.NET Core 3.0 이상의 유효성 검사 시스템은 Null을 허용하지 않는 매개 변수 또는 바인딩된 속성을 [Required]
특성을 포함한 것처럼 처리합니다. 자세한 내용은 [Required] 특성을 참조하세요.
게시
프로젝트 디렉터리에서 bin 폴더와 obj 폴더를 삭제합니다.
TestServer
제네릭 호스트로 TestServer를 직접 사용하는 앱의 경우 ConfigureWebHost에서 IWebHostBuilder에 TestServer
를 만듭니다.
[Fact]
public async Task GenericCreateAndStartHost_GetTestServer()
{
using var host = await new HostBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder
.UseTestServer()
.Configure(app => { });
})
.StartAsync();
var response = await host.GetTestServer().CreateClient().GetAsync("/");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
호환성이 손상되는 API 변경
호환성이 손상되는 변경 검토:
- ASP.NET Core 3.0 릴리스의 호환성이 손상되는 변경 전체 목록
- Antiforgery, CORS, Diagnostics, MVC 및 라우팅의 호환성이 손상되는 API 변경. 이 목록에는 호환성 스위치에 대한 주요 변경 내용이 포함되어 있습니다.
- 2.2에서 3.0으로 넘어가면서 .NET Core, ASP.NET Core, Entity Framework Core에서 발생한 호환성이 손상되는 변경에 대해 알아보려면 .NET Core 3.0의 호환성이 손상되는 변경을 참조하세요.
catch-all 매개 변수를 사용한 엔드포인트 라우팅
Warning
catch-all 매개 변수는 라우팅의 버그로 인해 경로와 일치하지 않을 수 있습니다. 이 버그의 영향을 받는 앱은 다음과 같은 특징이 있습니다.
- catch-all 경로(예:
{**slug}"
) - catch-all 경로가 일치해야 하는 요청과 일치하지 않습니다.
- 다른 경로를 제거하면 catch-all 경로 작동이 시작됩니다.
이 버그에 해당하는 사례는 GitHub 버그 18677 및 16579를 참조하세요.
이 버그에 대한 옵트인 픽스가 .NET Core 3.1.301 SDK 이상에 포함되어 있습니다. 다음 코드는 이 버그를 수정하는 내부 스위치를 설정합니다.
public static void Main(string[] args)
{
AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior",
true);
CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.
Azure App Service의 .NET Core 3.0
.NET Core의 Azure App Service로의 출시가 완료되었습니다. 이제 모든 Azure App Service 데이터 센터에서 .NET Core 3.0을 사용할 수 있습니다.
ASP.NET Core 모듈(ANCM)
Visual Studio를 설치할 때 ANCM(ASP.NET Core 모듈)이 선택된 구성 요소가 아니거나 이전 버전의 ANCM이 시스템에 설치된 경우, 최신 .NET Core 호스팅 번들 설치 관리자(직접 다운로드)를 다운로드하고 설치 관리자를 실행합니다. 자세한 내용은 호스팅 번들을 참조하세요.
ASP.NET Core