사용자 지정 .NET.NET Aspire 호스팅 통합 만들기
.NET .NET Aspire 애플리케이션 종속성을 신속하게 정렬하고 사용자 고유의 코드에 노출하는 데 사용할 수 있는 재사용 가능한 구성 요소를 제공하여 개발 환경을 개선합니다. Aspire기반 애플리케이션의 주요 구성 요소 중 하나는 리소스. 아래 코드를 고려합니다.
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("cache");
var db = builder.AddPostgres("pgserver")
.AddDatabase("inventorydb");
builder.AddProject<Projects.InventoryService>("inventoryservice")
.WithReference(redis)
.WithReference(db);
앞의 코드에는 다음과 같은 4개의 리소스가 표시됩니다.
-
cache
: Redis 컨테이너입니다. -
pgserver
: Postgres 컨테이너입니다. -
inventorydb
:pgserver
에서 호스팅된 데이터베이스입니다. -
inventoryservice
: ASP.NET Core 애플리케이션입니다.
평균 개발자가 작성하는 대부분의 .NET.NET Aspire관련 코드는 앱 모델 리소스를 추가하고 그 사이에 참조를 만드는 데 중점을 두고 있습니다.
.NET .NET Aspire 사용자 지정 리소스의 주요 요소
.NET .NET Aspire 사용자 지정 리소스를 빌드하려면 다음이 필요합니다.
- IResource 구현하는 사용자 지정 리소스 종류
-
{CustomResource}
라는 사용자 지정 리소스의 이름을 가진Add{CustomResource}
라는 IDistributedApplicationBuilder용 확장 메서드입니다.
사용자 지정 리소스에 선택적 구성이 필요한 경우 개발자는 작성기 패턴사용하여 이러한 구성 옵션을 검색할 수 있도록 With*
접미사 확장 메서드를 구현하려고 할 수 있습니다.
실용적인 예: MailDev
사용자 지정 리소스를 개발하는 방법을 이해하기 위해 이 문서에서는 MailDev위한 사용자 지정 리소스를 빌드하는 방법의 예를 보여 줍니다. MailDev 개발자가 앱 내에서 전자 메일 보내기 동작을 테스트할 수 있도록 설계된 로컬 메일 server 제공하는 오픈 소스 도구입니다. 자세한 내용은 MailDevGitHub 리포지토리참조하세요.
이 예제에서는 만든 MailDev 리소스에 대한 테스트 환경으로 새 .NET Aspire 프로젝트를 만듭니다. 기존 .NET Aspire 프로젝트에서 사용자 지정 리소스를 만들 수 있지만 사용자 지정 리소스를 여러 .NET Aspire기반 솔루션에서 사용할 수 있고 재사용 가능한 통합으로 개발해야 하는지 여부를 고려하는 것이 좋습니다.
시작 프로젝트 설정
개발 중인 새 리소스를 테스트하는 데 사용되는 새 .NET.NET Aspire 프로젝트를 만듭니다.
dotnet new aspire -o MailDevResource
cd MailDevResource
dir
프로젝트가 만들어지면 다음이 포함된 목록이 표시됩니다.
-
MailDevResource.AppHost
: 사용자 지정 리소스를 테스트하는 데 사용되는 앱 호스트. -
MailDevResource.ServiceDefaults
: 서비스는 기본적으로 서비스 관련 프로젝트에 사용할 프로젝트를 사용합니다. -
MailDevResource.sln
: 두 프로젝트를 참조하는 솔루션 파일입니다.
다음 명령을 실행하여 프로젝트를 성공적으로 빌드하고 실행할 수 있는지 확인합니다.
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj
콘솔 출력은 다음과 유사합니다.
Building...
info: Aspire.Hosting.DistributedApplication[0]
Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
Application host directory is:
..\docs-aspire\docs\extensibility\snippets\MailDevResource\MailDevResource.AppHost
info: Aspire.Hosting.DistributedApplication[0]
Now listening on: https://localhost:17251
info: Aspire.Hosting.DistributedApplication[0]
Login to the dashboard at https://localhost:17251/login?t=928db244c720c5022a7a9bf5cf3a3526
info: Aspire.Hosting.DistributedApplication[0]
Distributed application started. Press Ctrl+C to shut down.
브라우저에서
Ctrl+C 눌러 앱을 종료합니다(브라우저 탭을 닫을 수 있음).
리소스 확장용 라이브러리 만들기
.NET Aspire 리소스는 .NET Aspire 호스팅 라이브러리(Aspire.Hosting
)를 참조하는 클래스 라이브러리 내에 포함된 클래스 및 메서드일 뿐입니다. 리소스를 별도의 프로젝트에 배치하면 .NET.NET Aspire기반 앱 간에 리소스를 보다 쉽게 공유하고 잠재적으로 NuGet에서 패키지하고 공유할 수 있습니다.
MailDev.Hosting이라는 클래스 라이브러리 프로젝트를 만듭니다.
dotnet new classlib -o MailDev.Hosting
클래스 라이브러리에
Aspire.Hosting
패키지 참조로 추가합니다.dotnet add ./MailDev.Hosting/MailDev.Hosting.csproj package Aspire.Hosting --version 9.0.0
중요하다
여기서 지정하는 버전은 설치된 .NET.NET Aspire 워크로드의 버전과 일치해야 합니다.
MailDevResource.AppHost 프로젝트에 클래스 라이브러리 참조를 추가합니다.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
솔루션 파일에 클래스 라이브러리 프로젝트를 추가합니다.
dotnet sln ./MailDevResource.sln add ./MailDev.Hosting/MailDev.Hosting.csproj
다음 단계가 수행되면 프로젝트를 시작할 수 있습니다.
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
그러면 콘솔에 경고가 표시됩니다.
.\.nuget\packages\aspire.hosting.apphost\9.0.0\build\Aspire.Hosting.AppHost.targets(174,5): warning ASPIRE004: '..\MailDev.Hosting\MailDev.Hosting.csproj' is referenced by an A
spire Host project, but it is not an executable. Did you mean to set IsAspireProjectResource="false"? [D:\source\repos\docs-aspire\docs\extensibility\snippets\MailDevResource\MailDevResource.AppHost\MailDevRe
source.AppHost.csproj]
.NET
.NET Aspire 앱 호스트의 프로젝트 참조를 서비스 프로젝트인 것처럼 취급하기 때문입니다. 프로젝트 참조를 비서비스 프로젝트로 처리해야 한다고 .NET.NET Aspire에게 말하기 위해 MailDevResource.AppHostMailDevResource.AppHost.csproj 파일의 MailDev.Hosting
프로젝트 참조를 다음과 같이 수정합니다.
<ItemGroup>
<!-- The IsAspireProjectResource attribute tells .NET Aspire to treat this
reference as a standard project reference and not attempt to generate
a metadata file -->
<ProjectReference Include="..\MailDev.Hosting\MailDev.Hosting.csproj"
IsAspireProjectResource="false" />
</ItemGroup>
이제 앱 호스트를 시작할 때 콘솔에 경고가 표시되지 않습니다.
리소스 종류 정의
MailDev. 호스팅 클래스 라이브러리에는 리소스를 앱 호스트에 추가하기 위한 리소스 종류 및 확장 메서드가 포함되어 있습니다. 먼저 사용자 지정 리소스를 사용할 때 개발자에게 제공하려는 환경을 고려해야 합니다. 이 사용자 지정 리소스의 경우 개발자가 다음과 같은 코드를 작성할 수 있도록 합니다.
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.NewsletterService>("newsletterservice")
.WithReference(maildev);
이를 달성하기 위해서는 IResourceWithConnectionString을 구현하여 WithReference 확장을 사용하여 MailDevserver에 대한 연결 세부 정보를 연결 문자열로 삽입할 수 있도록 설계된 MailDevResource
이라는 사용자 지정 리소스가 필요합니다.
MailDev이 컨테이너 리소스로 제공되므로, ContainerResource에서 파생하여 .NET.NET Aspire의 다양한 기존 컨테이너 중심 확장을 활용할 수 있도록 할 것입니다.
MailDev.Hosting
프로젝트에서 Class1.cs 파일의 내용을 바꾸고 파일 이름을 다음 코드로 MailDevResource.cs 바꿉니다.
// For ease of discovery, resource types should be placed in
// the Aspire.Hosting.ApplicationModel namespace. If there is
// likelihood of a conflict on the resource name consider using
// an alternative namespace.
namespace Aspire.Hosting.ApplicationModel;
public sealed class MailDevResource(string name) : ContainerResource(name), IResourceWithConnectionString
{
// Constants used to refer to well known-endpoint names, this is specific
// for each resource type. MailDev exposes an SMTP endpoint and a HTTP
// endpoint.
internal const string SmtpEndpointName = "smtp";
internal const string HttpEndpointName = "http";
// An EndpointReference is a core .NET Aspire type used for keeping
// track of endpoint details in expressions. Simple literal values cannot
// be used because endpoints are not known until containers are launched.
private EndpointReference? _smtpReference;
public EndpointReference SmtpEndpoint =>
_smtpReference ??= new(this, SmtpEndpointName);
// Required property on IResourceWithConnectionString. Represents a connection
// string that applications can use to access the MailDev server. In this case
// the connection string is composed of the SmtpEndpoint endpoint reference.
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"smtp://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
);
}
앞의 사용자 지정 리소스에서 EndpointReference 및 ReferenceExpressionIManifestExpressionProvider, IValueProvider및 IValueWithReferences같은 인터페이스 컬렉션을 구현하는 여러 형식의 예입니다. 이러한 형식 및 .NET.NET Aspire에서의 역할에 대한 자세한 내용은 기술 세부 정보을 참조하세요.
리소스 확장 정의
개발자가 사용자 지정 리소스를 쉽게 사용할 수 있도록 AddMailDev
확장 메서드를 MailDev.Hosting 프로젝트에 추가해야 합니다.
AddMailDev
확장 메서드는 컨테이너로 성공적으로 시작할 수 있도록 리소스를 구성하는 역할을 담당합니다.
MailDev.Hosting 프로젝트의 새 파일 MailDevResourceBuilderExtensions.cs에 다음 코드를 추가합니다.
using Aspire.Hosting.ApplicationModel;
// Put extensions in the Aspire.Hosting namespace to ease discovery as referencing
// the .NET Aspire hosting package automatically adds this namespace.
namespace Aspire.Hosting;
public static class MailDevResourceBuilderExtensions
{
/// <summary>
/// Adds the <see cref="MailDevResource"/> to the given
/// <paramref name="builder"/> instance. Uses the "2.1.0" tag.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
/// <param name="name">The name of the resource.</param>
/// <param name="httpPort">The HTTP port.</param>
/// <param name="smtpPort">The SMTP port.</param>
/// <returns>
/// An <see cref="IResourceBuilder{MailDevResource}"/> instance that
/// represents the added MailDev resource.
/// </returns>
public static IResourceBuilder<MailDevResource> AddMailDev(
this IDistributedApplicationBuilder builder,
string name,
int? httpPort = null,
int? smtpPort = null)
{
// The AddResource method is a core API within .NET Aspire and is
// used by resource developers to wrap a custom resource in an
// IResourceBuilder<T> instance. Extension methods to customize
// the resource (if any exist) target the builder interface.
var resource = new MailDevResource(name);
return builder.AddResource(resource)
.WithImage(MailDevContainerImageTags.Image)
.WithImageRegistry(MailDevContainerImageTags.Registry)
.WithImageTag(MailDevContainerImageTags.Tag)
.WithHttpEndpoint(
targetPort: 1080,
port: httpPort,
name: MailDevResource.HttpEndpointName)
.WithEndpoint(
targetPort: 1025,
port: smtpPort,
name: MailDevResource.SmtpEndpointName);
}
}
// This class just contains constant strings that can be updated periodically
// when new versions of the underlying container are released.
internal static class MailDevContainerImageTags
{
internal const string Registry = "docker.io";
internal const string Image = "maildev/maildev";
internal const string Tag = "2.1.0";
}
앱 호스트 내에서 사용자 지정 통합 유효성 검사
이제 사용자 지정 리소스의 기본 구조가 완료되었으므로 실제 AppHost 프로젝트에서 테스트해야 합니다. MailDevResource.AppHost 프로젝트에서 Program.cs 파일을 열고 다음 코드로 업데이트합니다.
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.Build().Run();
Program.cs 파일을 업데이트한 후 앱 호스트 프로젝트를 시작하고 대시보드를 엽니다.
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
몇 분 후 대시보드는 maildev
리소스가 실행 중임을 표시하고 앱이 보내는 각 전자 메일의 콘텐츠를 보여 주는 MailDev 웹앱으로 이동하는 하이퍼링크를 사용할 수 있습니다.
.NET .NET Aspire 대시보드는 다음과 유사해야 합니다.
MailDev 웹앱은 다음과 유사해야 합니다.
테스트를 위해 앱 호스트에 .NET 서비스 프로젝트 추가
.NET Aspire MailDev 통합을 성공적으로 시작할 수 있게 되면 .NET 프로젝트 내에서 MailDev 연결 정보를 사용할 때입니다. 일반적으로 .NET.NET Aspire에서는 호스팅 패키지와 하나 이상의 구성 요소 패키지가존재한다. 예를 들어 다음을 고려합니다.
-
호스팅 패키지: 앱 모델 내의 리소스를 나타내는 데 사용됩니다.
Aspire.Hosting.Redis
-
구성 요소 패키지: client 라이브러리를 구성하고 사용하는 데 사용됩니다.
Aspire.StackExchange.Redis
Aspire.StackExchange.Redis.DistributedCaching
Aspire.StackExchange.Redis.OutputCaching
MailDev 리소스의 경우 .NET 플랫폼에는 이미 SmtpClient형식의 간단한 SMTP(메일 전송 프로토콜) client 있습니다. 이 예제에서는 단순성을 위해 이 기존 API를 사용하지만 다른 리소스 유형은 개발자를 지원하기 위해 사용자 지정 통합 라이브러리의 이점을 활용할 수 있습니다.
엔드 투 엔드 시나리오를 테스트하려면 MailDev 리소스에 대한 연결 정보를 삽입할 수 있는 .NET 프로젝트가 필요합니다. Web API 프로젝트를 추가합니다.
.NET 프로젝트를 MailDevResource.NewsletterService로 새로 만드세요.
dotnet new webapi --use-minimal-apis -o MailDevResource.NewsletterService
MailDev.Hosting 프로젝트에 대한 참조를 추가합니다.
dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
MailDevResource.AppHost 프로젝트에 대한 참조를 추가합니다.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
솔루션 파일에 새 프로젝트를 추가합니다.
dotnet sln ./MailDevResource.sln add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
프로젝트가 추가되고 참조가 업데이트된 후 MailDevResource.AppHost.csproj 프로젝트의 Program.cs 열고 원본 파일을 다음과 같이 업데이트합니다.
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.MailDevResource_NewsletterService>("newsletterservice")
.WithReference(maildev);
builder.Build().Run();
Program.cs 파일을 업데이트한 후 앱 호스트를 다시 시작합니다. 그런 다음 뉴스레터 서비스가 시작되었고 ConnectionStrings__maildev
환경 변수가 프로세스에 추가되었는지 확인합니다.
리소스 페이지에서 newsletterservice
행을 찾은 다음, 세부 정보 열의 보기 링크를 선택합니다.
위의 스크린샷은 newsletterservice
프로젝트의 환경 변수를 보여줍니다.
ConnectionStrings__maildev
환경 변수는 maildev
리소스에 의해 프로젝트에 삽입된 연결 문자열입니다.
연결 문자열을 사용하여 메시지 보내기
뉴스레터 서비스 프로젝트에 삽입된 SMTP 연결 세부 정보를 사용하려면 종속성 주입 컨테이너에 SmtpClient 인스턴스를 싱글톤으로 삽입합니다.
MailDevResource.NewsletterService 프로젝트의 Program.cs 파일에 다음 코드를 추가하여 싱글톤 서비스를 설정합니다.
Program
클래스에서 // Add services to the container
주석 바로 다음에 다음 코드를 추가합니다.
builder.Services.AddSingleton<SmtpClient>(sp =>
{
var smtpUri = new Uri(builder.Configuration.GetConnectionString("maildev")!);
var smtpClient = new SmtpClient(smtpUri.Host, smtpUri.Port);
return smtpClient;
});
팁
이 코드 조각은 공식 SmtpClient
에 의존하지만, 이 유형은 일부 플랫폼에서는 쓸모가 없으며 다른 플랫폼에서는 권장되지 않습니다.
MailKit사용하는 최신 방법은 사용자 지정 .NET Aspireclient 통합 만들기참조하세요.
client테스트하려면 뉴스레터 서비스에 두 가지 간단한 subscribe
및 unsubscribe
POST 메서드를 추가합니다.
MailDevResource.NewsletterService 프로젝트의 Program.cs 파일에 "weatherforecast" MapGet
호출을 대체하여 ASP.NET Core 경로를 설정하는 다음 코드를 추가합니다.
app.MapPost("/subscribe", async (SmtpClient smtpClient, string email) =>
{
using var message = new MailMessage("newsletter@yourcompany.com", email)
{
Subject = "Welcome to our newsletter!",
Body = "Thank you for subscribing to our newsletter!"
};
await smtpClient.SendMailAsync(message);
});
app.MapPost("/unsubscribe", async (SmtpClient smtpClient, string email) =>
{
using var message = new MailMessage("newsletter@yourcompany.com", email)
{
Subject = "You are unsubscribed from our newsletter!",
Body = "Sorry to see you go. We hope you will come back soon!"
};
await smtpClient.SendMailAsync(message);
});
팁
코드 편집기가 자동으로 추가하지 않는 경우 Program.cs 내에서 System.Net.Mail
및 Microsoft.AspNetCore.Mvc
네임스페이스를 참조해야 합니다.
Program.cs 파일이 업데이트되면 앱 호스트를 시작하고 브라우저를 사용하거나 curl
을 통해 다음 URL에 접속하십시오(또는 Visual Studio를 사용하는 경우 .http
파일을 사용할 수 있습니다).
POST /subscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
이 API를 사용하려면 curl
사용하여 요청을 보낼 수 있습니다. 다음 curl
명령은 HTTP POST
요청을 subscribe
엔드포인트로 보내며, 뉴스레터 구독을 위해 email
쿼리 문자열 값을 기대합니다. 요청 본문이 JSON 형식임을 나타내기 위해 Content-Type
헤더를 application/json
으로 설정합니다.
curl -H "Content-Type: application/json" --request POST https://localhost:7251/subscribe?email=test@test.com
다음 API는 unsubscribe
엔드포인트입니다. 이 엔드포인트는 뉴스레터에서 구독을 취소하는 데 사용됩니다.
POST /unsubscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
회보에서 구독을 취소하려면 다음 curl
명령을 사용하여 email
매개 변수를 쿼리 문자열로 unsubscribe
엔드포인트에 전달할 수 있습니다.
- Unix
-
Windows
curl -H "Content-Type: application/json" --request POST https://localhost:7251/unsubscribe?email=test@test.com
팁
확인하십시오. https://localhost:7251
를 실행 중인 앱 호스트의 URL을 가진 올바른 localhost 포트로 바꾸셔야 합니다.
이러한 API 호출이 성공적인 응답(HTTP 200, Ok)을 반환하는 경우 대시보드의 maildev
리소스에서 선택할 수 있고 MailDev UI SMTP 엔드포인트로 전송된 전자 메일을 표시합니다.
기술 세부 정보
다음 섹션에서는 .NET.NET Aspire위한 사용자 지정 리소스를 개발할 때 이해해야 하는 다양한 기술 세부 정보를 설명합니다.
보안 네트워킹
이 예제에서 MailDev 리소스는 HTTP 및 SMTP를 통해 호스트 컴퓨터에 노출되는 컨테이너 리소스입니다. MailDev 리소스는 개발 도구이며 프로덕션용으로 사용되지 않습니다. 대신 HTTPS를 사용하려면 MailDev: HTTPS구성을 참조하세요.
네트워크 엔드포인트를 노출하는 사용자 지정 리소스를 개발할 때 리소스의 보안 영향을 고려하는 것이 중요합니다. 예를 들어 리소스가 데이터베이스인 경우 데이터베이스가 안전하고 연결 문자열이 공용 인터넷에 노출되지 않도록 하는 것이 중요합니다.
ReferenceExpression
및 EndpointReference
형식
앞의 코드에서 MailDevResource
두 가지 속성을 가졌습니다.
-
SmtpEndpoint
: EndpointReference 형식입니다. -
ConnectionStringExpression
: ReferenceExpression 형식입니다.
이러한 형식은 .NET Aspire 전체에서 구성 데이터를 나타내는 데 사용되는 몇 가지 유형 중 하나이며, .NET Aspire 프로젝트가 실행되거나 Azure Developer CLI(azd
)같은 도구를 통해 클라우드에 게시될 때까지 완료되지 않습니다.
이러한 형식이 해결하는 데 도움이 되는 근본적인 문제는, 모든 정보가 사용 가능할 때까지 구체적인 구성 정보의 해결을 지연시키는 것입니다.
예를 들어 MailDevResource
는 IResourceWithConnectionString 인터페이스에 필요한 대로 ConnectionStringExpression
속성을 노출합니다. 속성의 형식은 ReferenceExpression이며, 이 형식은 보간된 문자열을 Create 메서드에 전달하여 생성됩니다.
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"smtp://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
);
Create 메서드의 서명은 다음과 같습니다.
public static ReferenceExpression Create(
in ExpressionInterpolatedStringHandler handler)
이것은 일반적인 String 인수가 아닙니다. 이 메서드는 보간된 문자열 템플릿과 그 안에 참조된 값을 캡처하여 사용자 지정 처리를 허용하기 위해 보간된 문자열 처리기 패턴을 사용합니다. .NET .NET Aspire의 경우, 이 세부 정보는 보간된 문자열에서 참조된 각 값이 사용 가능해질 때 평가될 수 있는 ReferenceExpression에 캡처됩니다.
실행 흐름은 다음과 같습니다.
-
IResourceWithConnectionString 구현하는 리소스가 모델에 추가됩니다(예:
AddMailDev(...)
). -
IResourceBuilder<MailDevResource>
는 IResourceWithConnectionString 구현자를 처리하기 위한 특수 오버로드가 있는 WithReference에 전달됩니다. -
WithReference
는 리소스를 ConnectionStringReference 인스턴스로 래핑하고, 이 개체는 .NET.NET Aspire 프로젝트가 빌드되고 실행을 시작한 후 평가되는 EnvironmentCallbackAnnotation에 캡처됩니다. - 연결 문자열을 참조하는 프로세스가 시작되면서 .NET.NET Aspire 식 평가를 시작합니다. 먼저 ConnectionStringReference 가져오고 IValueProvider.GetValueAsync호출합니다.
-
GetValueAsync
메서드는 ReferenceExpression 인스턴스를 가져오는 ConnectionStringExpression 속성의 값을 가져옵니다. - 그런 다음 IValueProvider.GetValueAsync 메서드가 GetValueAsync을 호출하여 이전에 캡처된 보간 문자열을 처리합니다.
- 보간된 문자열에는 EndpointReference과 같은 다른 참조 형식의 참조가 포함되며, 이들은 평가되어 실제 값으로 대체됩니다 (이 시점에서 사용 가능합니다).
매니페스트 발행
IManifestExpressionProvider 인터페이스는 배포 시 리소스 간에 연결 정보를 공유하는 문제를 해결하도록 설계되었습니다. 이 특정 문제에 대한 솔루션은 .NET.NET Aspire 내부 루프 네트워킹 개요설명되어 있습니다. 로컬 개발과 마찬가지로 앱을 구성하는 데 많은 값이 필요하지만 azd
(Azure Developer CLI)와 같은 도구를 통해 앱을 배포할 때까지는 확인할 수 없습니다.
이 문제를 해결하기 위해 .NET.NET Aspireazd
및 기타 배포 도구가 해석하는 매니페스트 파일 생성합니다. 리소스 간의 연결 정보에 대한 구체적인 값을 지정하는 대신 배포 도구가 평가하는 식 구문이 사용됩니다. 일반적으로 매니페스트 파일은 개발자에게 표시되지 않지만 수동 검사를 위해 매니페스트 파일을 생성할 수 있습니다. 아래 명령은 앱 호스트에서 매니페스트를 생성하는 데 사용할 수 있습니다.
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj -- --publisher manifest --output-path aspire-manifest.json
이 명령은 다음과 같은 매니페스트 파일을 생성합니다.
{
"resources": {
"maildev": {
"type": "container.v0",
"connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}",
"image": "docker.io/maildev/maildev:2.1.0",
"bindings": {
"http": {
"scheme": "http",
"protocol": "tcp",
"transport": "http",
"targetPort": 1080
},
"smtp": {
"scheme": "tcp",
"protocol": "tcp",
"transport": "tcp",
"targetPort": 1025
}
}
},
"newsletterservice": {
"type": "project.v0",
"path": "../MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj",
"env": {
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
"ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true",
"ConnectionStrings__maildev": "{maildev.connectionString}"
},
"bindings": {
"http": {
"scheme": "http",
"protocol": "tcp",
"transport": "http"
},
"https": {
"scheme": "https",
"protocol": "tcp",
"transport": "http"
}
}
}
}
}
MailDevResource
.NET
.NET Aspire 매니페스트 게시 논리를 IResourceWithConnectionString 구현하므로 MailDevResource
컨테이너 리소스임에도 connectionString
필드가 필요하다는 것을 알고 있습니다.
connectionString
필드는 매니페스트에서 maildev
리소스의 다른 부분을 참조하여 최종 문자열을 생성합니다.
{
// ... other content omitted.
"connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}"
}
.NET .NET Aspire ConnectionStringExpression 살펴보고 IManifestExpressionProvider 인터페이스를 통해 최종 문자열을 빌드하기 때문에 이 문자열을 구성하는 방법을 알고 있습니다(IValueProvider 인터페이스가 사용되는 것과 거의 동일한 방식).
MailDevResource
는 ContainerResource에서 파생되기 때문에 매니페스트에 자동으로 포함됩니다. 리소스 작성자는 리소스 작성기에서 ExcludeFromManifest 확장 메서드를 사용하여 매니페스트에 콘텐츠를 출력하지 않을 수 있습니다.
public static IResourceBuilder<MailDevResource> AddMailDev(
this IDistributedApplicationBuilder builder,
string name,
int? httpPort = null,
int? smtpPort = null)
{
var resource = new MailDevResource(name);
return builder.AddResource(resource)
.WithImage(MailDevContainerImageTags.Image)
.WithImageRegistry(MailDevContainerImageTags.Registry)
.WithImageTag(MailDevContainerImageTags.Tag)
.WithHttpEndpoint(
targetPort: 1080,
port: httpPort,
name: MailDevResource.HttpEndpointName)
.WithEndpoint(
targetPort: 1025,
port: smtpPort,
name: MailDevResource.SmtpEndpointName)
.ExcludeFromManifest(); // This line was added
}
리소스가 매니페스트에 있어야 하는지 또는 리소스를 제외해야 하는지에 대해 신중하게 고려해야 합니다. 리소스가 매니페스트에 추가되는 경우 안전하고 안전하게 사용할 수 있도록 구성해야 합니다.
요약
사용자 지정 리소스 자습서에서는 기존 컨테이너화된 애플리케이션(MailDev)을 사용하는 사용자 지정 .NET Aspire 리소스를 만드는 방법을 알아보았습니다. 그런 다음 앱 내에서 사용할 수 있는 전자 메일 기능을 쉽게 테스트할 수 있도록 하여 로컬 개발 환경을 개선하는 데 사용했습니다. 이러한 학습은 .NET.NET Aspire기반 애플리케이션에서 사용할 수 있는 다른 사용자 지정 리소스를 빌드하는 데 적용할 수 있습니다. 이 특정 예제에는 사용자 지정 통합이 포함되지 않았지만 개발자가 리소스를 더 쉽게 사용할 수 있도록 사용자 지정 통합을 빌드할 수 있습니다. 이 시나리오에서는 .NET 플랫폼의 기존 SmtpClient
클래스를 사용하여 전자 메일을 보낼 수 있었습니다.
다음 단계
.NET Aspire