다음을 통해 공유


ASP.NET Core Blazor에서 웹 API 호출

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Warning

이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조 하세요. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

이 문서에서는 Blazor 앱에서 웹 API를 호출하는 방법을 설명합니다.

Package(패키지)

이 패키지는 System.Net.Http.Json .를 사용하여 System.Text.Json자동 serialization 및 System.Net.Http.HttpContent 역직렬화를 수행하는 확장 메서드 System.Net.Http.HttpClient 를 제공합니다. 패키지는 System.Net.Http.Json .NET 공유 프레임워크에서 제공되며 앱에 패키지 참조를 추가할 필요가 없습니다.

샘플 앱

GitHub 리포지토리의 dotnet/blazor-samples 샘플 앱을 참조하세요.

BlazorWebAppCallWebApi

다음에서 todo 목록 웹 API에 Blazor Web App없는 외부를 Blazor Web App호출합니다.

  • Backend: 최소 API를 기반으로 할 일 목록을 유지 관리하기 위한 웹 API 앱입니다. 웹 API 앱은 다른 서버에서 Blazor Web App호스트되는 별도의 앱입니다.
  • BlazorApp/BlazorApp.ClientBlazor Web App: 할 일 목록에서 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업과 같은 todo 목록 작업으로 웹 API 앱을 HttpClient 호출하는 A입니다.

대화형 WebAssembly 구성 요소와 CSR을 채택한 자동 구성 요소를 포함하는 CSR(클라이언트 쪽 렌더링)의 경우 클라이언트 프로젝트의 파일에 미리 등록된 HttpClient Program 호출이 이루어집니다(BlazorApp.Client):.

builder.Services.AddScoped(sp =>
    new HttpClient
    {
        BaseAddress = new Uri(builder.Configuration["FrontendUrl"] ?? "https://localhost:5002")
    });

미리 렌더링된 대화형 서버 구성 요소, 미리 렌더링된 WebAssembly 구성 요소 및 SSR을 미리 렌더링하거나 채택한 자동 구성 요소를 포함하는 SSR(서버 쪽 렌더링)의 경우 서버 프로젝트의 파일에 등록된 Program 호출이 수행 HttpClient 됩니다(BlazorApp).

builder.Services.AddHttpClient();

API가 다음의 Blazor Web App서버 프로젝트에 Blazor Web App있는 내부(동영상 목록 API 내부)를 호출합니다.

  • BlazorAppBlazor Web App: 동영상 목록을 유지 관리하는 A:
    • 서버의 앱 내 동영상 목록에서 작업을 수행하는 경우 일반 API 호출이 사용됩니다.
    • 웹 기반 클라이언트에서 API 호출을 수행하면 최소 API를 기반으로 영화 목록 작업에 웹 API가 사용됩니다.
  • BlazorApp.Client: 동영상 목록의 Blazor Web App사용자 관리를 위한 대화형 WebAssembly 및 자동 구성 요소가 포함된 클라이언트 프로젝트입니다.

CSR을 채택한 대화형 WebAssembly 구성 요소 및 자동 구성 요소를 포함하는 CSR의 경우 API에 대한 호출은 클라이언트 프로젝트()의 파일에 미리 등록된 Program HttpClient 것을 사용하는 클라이언트 기반 서비스(ClientMovieServiceBlazorApp.Client)를 통해 이루어집니다. 이러한 호출은 퍼블릭 또는 프라이빗 웹을 통해 이루어지므로 영화 목록 API는 웹 API입니다.

다음 예제에서는 엔드포인트에서 /movies 영화 목록을 가져옵니다.

public class ClientMovieService(HttpClient http) : IMovieService
{
    public async Task<Movie[]> GetMoviesAsync(bool watchedMovies) => 
        await http.GetFromJsonAsync<Movie[]>("movies") ?? [];
}

미리 렌더링된 대화형 서버 구성 요소, 미리 렌더링된 WebAssembly 구성 요소 및 SSR을 미리 렌더링하거나 채택한 자동 구성 요소를 포함하는 SSR의 경우 서버 기반 서비스(ServerMovieService)를 통해 직접 호출됩니다. API는 네트워크에 의존하지 않으므로 영화 목록 CRUD 작업에 대한 표준 API입니다.

다음 예제에서는 영화 목록을 가져옵니다.

public class ServerMovieService(MovieContext db) : IMovieService
{
    public async Task<Movie[]> GetMoviesAsync(bool watchedMovies) => 
        watchedMovies ? 
        await db.Movies.Where(t => t.IsWatched).ToArrayAsync() : 
        await db.Movies.ToArrayAsync();
}

BlazorWebAppCallWebApi_Weather

날씨 데이터에 스트리밍 렌더링을 사용하는 날씨 데이터 샘플 앱입니다.

BlazorWebAssemblyCallWebApi

앱에서 할 일 목록 웹 API를 호출합니다.Blazor WebAssembly

외부 웹 API를 호출하기 위한 서버 쪽 시나리오

서버 기반 구성 요소는 인스턴스를 사용하여 외부 웹 API를 호출하며, 일반적으로 .를 사용하여 HttpClient IHttpClientFactory생성됩니다. 서버 쪽 앱 에 적용되는 지침은 ASP.NET Core에서 IHttpClientFactory를 사용하여 HTTP 요청 만들기를 참조하세요.

서버 쪽 앱에는 서비스가 포함되지 HttpClient 않습니다. HttpClient 팩터리 인프라를 사용하여 앱에 HttpClient를 제공합니다.

Program 파일에서:

builder.Services.AddHttpClient();

다음 Razor 구성 요소는 GitHub 분기에 대한 Web API 요청을 ASP.NET Core에서 IHttpClientFactory를 사용하여 HTTP 요청 만들기 문서의 기본 사용법 예제와 유사하게 만듭니다.

CallWebAPI.razor:

@page "/call-web-api"
@using System.Text.Json
@using System.Text.Json.Serialization
@inject IHttpClientFactory ClientFactory

<h1>Call web API from a Blazor Server Razor component</h1>

@if (getBranchesError || branches is null)
{
    <p>Unable to get branches from GitHub. Please try again later.</p>
}
else
{
    <ul>
        @foreach (var branch in branches)
        {
            <li>@branch.Name</li>
        }
    </ul>
}

@code {
    private IEnumerable<GitHubBranch>? branches = [];
    private bool getBranchesError;
    private bool shouldRender;

    protected override bool ShouldRender() => shouldRender;

    protected override async Task OnInitializedAsync()
    {
        var request = new HttpRequestMessage(HttpMethod.Get,
            "https://api.github.com/repos/dotnet/AspNetCore.Docs/branches");
        request.Headers.Add("Accept", "application/vnd.github.v3+json");
        request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

        var client = ClientFactory.CreateClient();

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            using var responseStream = await response.Content.ReadAsStreamAsync();
            branches = await JsonSerializer.DeserializeAsync
                <IEnumerable<GitHubBranch>>(responseStream);
        }
        else
        {
            getBranchesError = true;
        }

        shouldRender = true;
    }

    public class GitHubBranch
    {
        [JsonPropertyName("name")]
        public string? Name { get; set; }
    }
}

위의 C# 12 이상 예제에서는 변수에 대해 빈 배열([])이 branches 만들어집니다. 이전 버전의 C#의 경우 빈 배열(Array.Empty<GitHubBranch>())을 만듭니다.

추가 작업 예제는 ASP.NET Core Blazor 파일 업로드 문서의 웹 API 컨트롤러에 파일을 업로드하는 서버 쪽 파일 업로드 예제를 참조하세요.

웹 API 호출에 대한 서비스 추상화

이 섹션은 Blazor Web App서버 프로젝트에서 웹 API를 유지 관리하거나 웹 API 호출을 외부 웹 API로 변환하는 S에 적용됩니다.

대화형 WebAssembly 및 자동 렌더링 모드를 사용하는 경우 구성 요소는 기본적으로 미리 렌더링됩니다. 또한 번들이 클라이언트에 다운로드되고 클라이언트 쪽 런타임이 활성화되기 전에 Blazor 자동 구성 요소가 서버에서 대화형으로 처음 렌더링됩니다. 즉, 이러한 렌더링 모드를 사용하는 구성 요소는 클라이언트와 서버 모두에서 성공적으로 실행되도록 설계되어야 합니다. 구성 요소가 클라이언트에서 실행할 때 서버 프로젝트 기반 API를 호출하거나 외부 웹 API(외부에 Blazor Web App있는 웹 API)로 요청을 변환해야 하는 경우 API가 서비스 인터페이스 뒤에서 호출하고 서비스의 클라이언트 및 서버 버전을 구현하는 것이 좋습니다.

  • 클라이언트 버전은 미리 구성된 HttpClient웹 API를 호출합니다.
  • 서버 버전은 일반적으로 서버 쪽 리소스에 직접 액세스할 수 있습니다. HttpClient 네트워크 요청은 일반적으로 불필요하기 때문에 서버에 다시 호출하는 서버에 삽입하는 것은 권장되지 않습니다. 또는 API가 서버 프로젝트 외부에 있을 수 있지만 프록시된 요청에 액세스 토큰을 추가하는 등의 방법으로 요청을 변환하려면 서버에 대한 서비스 추상화가 필요합니다.

WebAssembly 렌더링 모드를 사용하는 경우 미리 렌더링을 사용하지 않도록 설정하는 옵션도 있으므로 구성 요소는 클라이언트에서만 렌더링됩니다. 자세한 내용은 ASP.NET Core Blazor 렌더링 모드를 참조하세요.

예제(샘플 앱):

  • 샘플 앱의 BlazorWebAppCallWebApi 동영상 목록 웹 API입니다.
  • 샘플 앱에서 BlazorWebAppCallWebApi_Weather 날씨 데이터 웹 API를 렌더링하는 스트리밍.
  • 날씨 데이터는 (비 BFF 패턴) 또는 BlazorWebAppOidcBff (BFF 패턴) 샘플 앱에서 BlazorWebAppOidc 클라이언트로 반환됩니다. 이러한 앱은 보안(웹) API 호출을 보여 줍니다. 자세한 내용은 OIDC(OpenID Connect)를 사용하여 ASP.NET Core Blazor Web App 보안을 참조하세요.

Blazor Web App 외부 웹 API

이 섹션은 다른 서버에서 호스트될 Blazor Web App수 있는 별도의(외부) 프로젝트에서 유지 관리하는 웹 API를 호출하는 s에 적용됩니다.

Blazor Web App는 일반적으로 클라이언트 쪽 WebAssembly 구성 요소를 미리 렌더링하고 자동 구성 요소는 정적 또는 대화형 SSR(서버 쪽 렌더링) 중에 서버에 렌더링됩니다. HttpClient 서비스는 기본적으로 Blazor Web App'의 기본 프로젝트에 등록되지 않습니다. 서비스 추가 HttpClient 섹션에 .Client 설명된 대로 프로젝트에 등록된 서비스만 HttpClient 사용하여 앱을 실행하는 경우 앱을 실행하면 런타임 오류가 발생합니다.

InvalidOperationException: '... {COMPONENT}'. 'System.Net.Http.HttpClient' 형식의 등록된 서비스가 없습니다.

다음 방식 중 하나를 사용합니다.

  • HttpClient SSR 중에 사용할 수 있도록 HttpClient 서버 프로젝트에 서비스를 추가합니다. 서버 프로젝트의 Program 파일에서 다음 서비스 등록을 사용합니다.

    builder.Services.AddHttpClient();
    

    HttpClient 서비스는 공유 프레임워크에서 제공되므로 앱의 프로젝트 파일에서 패키지 참조가 필요하지 않습니다.

    예: 샘플 앱에서 웹 API를 나열하는 BlazorWebAppCallWebApi Todo

  • 웹 API를 호출하는 WebAssembly 구성 요소에 사전 렌더링이 필요하지 않은 경우 ASP.NET Core Blazor 렌더링 모드지침에 따라 미리 렌더링을 사용하지 않도록 설정합니다. 이 방법을 채택하는 경우 구성 요소가 서버에서 미리 렌더링되지 않으므로 서비스를 기본 프로젝트에 Blazor Web App 추가할 HttpClient 필요가 없습니다.

자세한 내용은 미리 렌더링하는 동안 클라이언트 쪽 서비스가 확인되지 않습니다.

미리 렌더링된 데이터

미리 렌더링할 때 구성 요소는 두 번 렌더링됩니다. 먼저 정적으로 렌더링한 다음 대화형으로 렌더링합니다. 상태는 미리 렌더링된 구성 요소에서 대화형 구성 요소로 자동으로 흐르지 않습니다. 구성 요소가 비동기 초기화 작업을 수행하고 초기화 중에 다른 상태에 대해 다른 콘텐츠를 렌더링하는 경우(예: "로드 중..." 진행률 표시기에서 구성 요소가 두 번 렌더링되면 깜박임이 표시할 수 있습니다.

앱과 BlazorWebAppCallWebApi_Weather 샘플 앱에서 보여 주는 영구 구성 요소 상태 API BlazorWebAppCallWebApi 를 사용하여 미리 렌더링된 상태를 전달하여 이 문제를 해결할 수 있습니다. 구성 요소가 대화형으로 렌더링되면 동일한 상태를 사용하여 동일한 방식으로 렌더링할 수 있습니다. 그러나 API는 현재 향상된 탐색에서 작동하지 않으므로 페이지(data-enhanced-nav=false)에 대한 링크에서 향상된 탐색을 사용하지 않도록 설정하여 해결할 수 있습니다. 자세한 내용은 다음 리소스를 참조하세요.

HttpClient 서비스 추가

이 섹션의 지침은 클라이언트 쪽 시나리오에 적용됩니다.

클라이언트 쪽 구성 요소는 미리 구성된 HttpClient 서비스를 사용하여 웹 API를 호출하며, 이 서비스는 원본 서버로 다시 요청을 만드는 데 중점을 줍니다. 개발자 코드에서 다른 웹 API에 대한 추가 HttpClient 서비스 구성을 만들 수 있습니다. 요청은 Blazor JSON 도우미 또는 HttpRequestMessage를 사용하여 구성됩니다. 요청에는 Fetch API 옵션 구성이 포함될 수 있습니다.

이 섹션의 구성 예제는 단일 웹 API가 앱의 단일 HttpClient 인스턴스에 대해 호출되는 경우에만 유용합니다. 앱이 각각 자체 기본 주소 및 구성을 사용하여 여러 웹 API를 호출해야 하는 경우 이 문서의 뒷부분에서 설명하는 다음 방법을 채택할 수 있습니다.

  • IHttpClientFactory명명됨HttpClient: 각 웹 API에는 고유한 이름이 제공됩니다. 앱 코드 또는 Razor 구성 요소가 웹 API를 호출할 때 명명된 HttpClient 인스턴스를 사용하여 호출합니다.
  • 형식화 HttpClient: 각 웹 API가 입력됩니다. 앱 코드 또는 Razor 구성 요소가 웹 API를 호출할 때 형식화된 HttpClient 인스턴스를 사용하여 호출합니다.

Program 파일에서 앱을 만드는 데 사용되는 프로젝트 템플릿에 Blazor 서비스가 아직 없는 경우 서비스를 추가 HttpClient 합니다.

builder.Services.AddScoped(sp => 
    new HttpClient
    {
        BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
    });

앞의 예제에서는 앱의 기본 주소를 가져오고 일반적으로 호스트 페이지의 태그 href 값에서 <base> 파생되는 (IWebAssemblyHostEnvironment.BaseAddress)로 기본 주소를 builder.HostEnvironment.BaseAddress 설정합니다.

클라이언트의 자체 기본 주소를 사용하는 가장 일반적인 사용 사례는 다음과 같습니다.

  • (.NET 8 이상)의 Blazor Web App 클라이언트 프로젝트(.Client)는 WebAssembly 구성 요소 또는 WebAssembly의 클라이언트에서 실행되는 코드에서 서버 앱의 API로 웹 API를 호출합니다.
  • 호스트된 Blazor WebAssembly 앱의 클라이언트 프로젝트(Client)는 서버 프로젝트(Server)에 대한 웹 API 호출을 만듭니다. 호스트 Blazor WebAssembly 된 프로젝트 템플릿은 .NET 8 이상에서 더 이상 사용할 수 없습니다. 그러나 호스트된 Blazor WebAssembly 앱은 .NET 8에서 계속 지원됩니다.

외부 웹 API를 호출하는 경우(클라이언트 앱과 동일한 URL 공간에 있지 않음) 웹 API의 기본 주소로 URI를 설정합니다. 다음 예제에서는 웹 API https://localhost:5001의 기본 주소를 별도의 웹 API 앱이 실행되고 클라이언트 앱의 요청에 응답할 준비가 되는 위치로 설정합니다.

builder.Services.AddScoped(sp => 
    new HttpClient
    {
        BaseAddress = new Uri("https://localhost:5001")
    });

JSON 도우미

HttpClient는 원본 서버에 대해 다시 요청을 수행하기 위해 미리 구성된 서비스로 사용할 수 있습니다.

HttpClient 및 JSON 도우미(System.Net.Http.Json.HttpClientJsonExtensions)는 타사 웹 API 엔드포인트를 호출하는 데에도 사용됩니다. HttpClient는 브라우저의 Fetch API를 사용하여 구현되며, CORS(원본 간 리소스 공유) 섹션의 뒷부분에서 설명하는 동일한 원본 정책의 적용을 포함하여 제한 사항이 적용됩니다.

클라이언트의 기본 주소가 원래 서버의 주소로 설정됩니다. @inject 지시문을 사용하여 HttpClient 인스턴스를 구성 요소에 삽입합니다.

@using System.Net.Http
@inject HttpClient Http

GetFromJsonAsync, PutAsJsonAsyncPostAsJsonAsync를 포함하여 HttpClientJsonExtensions에 대한 액세스에 System.Net.Http.Json 네임스페이스를 사용합니다.

@using System.Net.Http.Json

다음 섹션에서는 JSON 도우미를 다룹니다.

System.Net.Http 에는 HTTP 요청을 보내고 HTTP 응답을 받기 위한 추가 메서드(예: DELETE 요청 보내기)가 포함되어 있습니다. 자세한 내용은 DELETE 및 추가 확장 메서드 섹션을 참조하세요.

JSON에서 GET(GetFromJsonAsync)

GetFromJsonAsync는 HTTP GET 요청을 보내고 JSON 응답 본문을 구문 분석하여 개체를 만듭니다.

다음 구성 요소 코드에서 todoItems는 구성 요소에 의해 표시됩니다. 구성 요소의 초기화가 완료되면 GetFromJsonAsync가 호출됩니다(OnInitializedAsync).

todoItems = await Http.GetFromJsonAsync<TodoItem[]>("todoitems");

JSON으로 POST(PostAsJsonAsync)

PostAsJsonAsync는 요청 본문에서 JSON으로 직렬화된 값을 포함하는 지정된 URI에 POST 요청을 보냅니다.

다음 구성 요소 코드에서 구성 요소의 바인딩된 요소는 newItemName을 제공합니다. AddItem 메서드는 <button> 요소를 선택하여 트리거됩니다.

await Http.PostAsJsonAsync("todoitems", addItem);

PostAsJsonAsyncHttpResponseMessage을 반환합니다. 응답 메시지에서 JSON 콘텐츠를 역직렬화하려면 ReadFromJsonAsync 확장 메서드를 사용합니다. 다음 예제에서는 JSON 날씨 데이터를 배열로 읽습니다.

var content = await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ?? 
    Array.Empty<WeatherForecast>();

JSON으로 PUT(PutAsJsonAsync)

PutAsJsonAsync는 JSON 인코딩 콘텐츠와 함께 HTTP PUT 요청을 보냅니다.

다음 구성 요소 코드에서 구성 요소의 바인딩된 요소는 NameIsCompleted에 대한 editItem 값을 제공합니다. 항목의 Id는 UI의 다른 부분에서 해당 항목을 선택하고(표시되지 않음) EditItem을 호출하면 설정됩니다. SaveItem 메서드는 <button> 요소를 선택하여 트리거됩니다. 다음 예제에서는 간결성을 위해 로드를 todoItems 표시하지 않습니다. 항목을 로드하는 예제는 JSON(GetFromJsonAsync) 섹션의 GET을 참조하세요.

await Http.PutAsJsonAsync($"todoitems/{editItem.Id}", editItem);

PutAsJsonAsyncHttpResponseMessage을 반환합니다. 응답 메시지에서 JSON 콘텐츠를 역직렬화하려면 ReadFromJsonAsync 확장 메서드를 사용합니다. 다음 예제에서는 JSON 날씨 데이터를 배열로 읽습니다.

var content = await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ?? 
    Array.Empty<WeatherForecast>();

PATCH as JSON(PatchAsJsonAsync)

PatchAsJsonAsync 는 JSON으로 인코딩된 콘텐츠를 사용하여 HTTP PATCH 요청을 보냅니다.

참고 항목

자세한 내용은 ASP.NET Core 웹 API의 JsonPatch를 참조하세요.

다음 예제 PatchAsJsonAsync 에서는 JSON PATCH 문서를 이스케이프된 따옴표가 있는 일반 텍스트 문자열로 받습니다.

await Http.PatchAsJsonAsync(
    $"todoitems/{id}", 
    "[{\"operationType\":2,\"path\":\"/IsComplete\",\"op\":\"replace\",\"value\":true}]");

PatchAsJsonAsyncHttpResponseMessage을 반환합니다. 응답 메시지에서 JSON 콘텐츠를 역직렬화하려면 ReadFromJsonAsync 확장 메서드를 사용합니다. 다음 예제에서는 JSON todo 항목 데이터를 배열로 읽습니다. 메서드에서 항목 데이터가 반환되지 않으면 빈 배열이 만들어지므로 content 문이 실행된 후에는 null이 아닙니다.

var response = await Http.PatchAsJsonAsync(...);
var content = await response.Content.ReadFromJsonAsync<TodoItem[]>() ??
    Array.Empty<TodoItem>();

들여쓰기, 간격 및 이스케이프되지 않은 따옴표로 배치된 인코딩되지 않은 PATCH 문서는 다음 JSON으로 표시됩니다.

[
  {
    "operationType": 2,
    "path": "/IsComplete",
    "op": "replace",
    "value": true
  }
]

PATCH 요청을 실행하는 앱에서 PATCH 문서 만들기를 간소화하기 위해 앱은 다음 지침에 따라 .NET JSON PATCH 지원을 사용할 수 있습니다.

Microsoft.AspNetCore.JsonPatch NuGet 패키지를 설치하고 패키지의 API 기능을 사용하여 PATCH 요청을 작성 JsonPatchDocument 합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.

구성 요소의 System.Text.Json맨 위에 Razor , System.Text.Json.SerializationMicrosoft.AspNetCore.JsonPatch 네임스페이스에 대한 지시문을 추가 @using 합니다.

@using System.Text.Json
@using System.Text.Json.Serialization
@using Microsoft.AspNetCore.JsonPatch

메서드를 JsonPatchDocument 사용하도록 설정된 true for를 IsComplete TodoItem 작성합니다Replace.

var patchDocument = new JsonPatchDocument<TodoItem>()
    .Replace(p => p.IsComplete, true);

문서의 작업(patchDocument.Operations)을 호출에 PatchAsJsonAsync 전달합니다.

private async Task UpdateItem(long id)
{
    await Http.PatchAsJsonAsync(
        $"todoitems/{id}", 
        patchDocument.Operations, 
        new JsonSerializerOptions()
        {
            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
        });
}

JsonSerializerOptions.DefaultIgnoreCondition 는 해당 형식의 기본값과 같은 경우에만 속성을 무시하도록 JsonIgnoreCondition.WhenWritingDefault 설정됩니다.

표시를 위해 true JSON 페이로드를 쾌적한 형식으로 표시하려는 경우 집합을 추가 JsonSerializerOptions.WriteIndented 합니다. 들여쓰기된 JSON 작성은 PATCH 요청 처리와 관련이 없으며 일반적으로 웹 API 요청에 대한 프로덕션 앱에서 수행되지 않습니다.

ASP.NET Core 웹 API 문서의 JsonPatch에 있는 지침 에 따라 웹 API 에 PATCH 컨트롤러 작업을 추가합니다. 또는 다음 단계를 통해 PATCH 요청 처리를 최소 API구현할 수 있습니다.

NuGet 패키지에 대한 패키지 참조를 Microsoft.AspNetCore.Mvc.NewtonsoftJson 웹 API 앱에 추가합니다.

참고 항목

패키지에 대한 참조가 자동으로 패키지 참조를 추가하므로 앱에 패키지에 대한 Microsoft.AspNetCore.JsonPatch Microsoft.AspNetCore.JsonPatch패키지 참조를 Microsoft.AspNetCore.Mvc.NewtonsoftJson 추가할 필요가 없습니다.

파일에서 Program 네임스페이 @using 스에 대한 Microsoft.AspNetCore.JsonPatch 지시문을 추가합니다.

using Microsoft.AspNetCore.JsonPatch;

웹 API의 요청 처리 파이프라인에 엔드포인트를 제공합니다.

app.MapPatch("/todoitems/{id}", async (long id, TodoContext db) =>
{
    if (await db.TodoItems.FindAsync(id) is TodoItem todo)
    {
        var patchDocument = 
            new JsonPatchDocument<TodoItem>().Replace(p => p.IsComplete, true);
        patchDocument.ApplyTo(todo);
        await db.SaveChangesAsync();

        return TypedResults.Ok(todo);
    }

    return TypedResults.NoContent();
});

Warning

ASP.NET Core 웹 API 문서의 JsonPatch에 있는 다른 예제와 마찬가지로 이전 PATCH API는 웹 API를 과도하게 게시하는 공격으로부터 보호하지 않습니다. 자세한 내용은 자습서: ASP.NET Core를 사용하여 웹 API 만들기를 참조 하세요.

완전히 작동하는 PATCH 환경은 샘플 앱을 참조 BlazorWebAppCallWebApi 하세요.

DELETE(DeleteAsync) 및 추가 확장 메서드

System.Net.Http는 HTTP 요청을 보내고 HTTP 응답을 받기 위한 추가 확장 메서드를 포함합니다. HttpClient.DeleteAsync는 웹 API에 HTTP DELETE 요청을 보내는 데 사용됩니다.

다음 구성 요소 코드에서 <button> 요소는 DeleteItem 메서드를 호출합니다. 바인딩된 <input> 요소는 삭제할 항목의 id를 제공합니다.

await Http.DeleteAsync($"todoitems/{id}");

HttpClientIHttpClientFactory로 명명함

IHttpClientFactory 서비스 및 명명된 HttpClient의 구성이 지원됩니다.

참고 항목

IHttpClientFactory에서는 명명된 HttpClient를 사용하는 대신 형식화된 HttpClient를 사용하는 것이 좋습니다. 자세한 내용은 형식화된 HttpClient 섹션을 참조하세요.

앱에 Microsoft.Extensions.Http NuGet 패키지를 추가합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.

Program 클라이언트 프로젝트의 파일에서:

builder.Services.AddHttpClient("WebAPI", client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

명명된 클라이언트를 미리 렌더링된 클라이언트 쪽 구성 요소 Blazor Web App에서 사용하는 경우 이전 서비스 등록이 서버 프로젝트와 .Client 프로젝트 모두에 표시되어야 합니다. 서버 builder.HostEnvironment.BaseAddress 에서 웹 API의 기본 주소로 바뀝니다. 이 주소는 아래에 자세히 설명되어 있습니다.

앞의 클라이언트 쪽 예제에서는 클라이언트 쪽 앱의 기본 주소를 가져오고 일반적으로 호스트 페이지의 태그 href 값에서 <base> 파생되는 (IWebAssemblyHostEnvironment.BaseAddress)로 기본 주소를 builder.HostEnvironment.BaseAddress 설정합니다.

클라이언트의 자체 기본 주소를 사용하는 가장 일반적인 사용 사례는 다음과 같습니다.

  • WebAssembly/Auto 구성 요소 또는 WebAssembly의 클라이언트에서 실행되는 코드에서 동일한 호스트 주소의 Blazor Web App 서버 앱의 API로 웹 API를 호출하는 클라이언트 프로젝트(.Client)입니다.
  • 서버 프로젝트(Client)에 웹 API를 호출하는 호스트 Blazor WebAssembly 된 앱의 클라이언트 프로젝트(Server)입니다.

클라이언트의 기본 주소를 사용하는 가장 일반적인 사용 사례는 웹 API를 서버 프로젝트(Client)에 호출하는 호스트된 Blazor WebAssembly 앱의 클라이언트 프로젝트(Server)에 있습니다.

외부 웹 API를 호출하거나(클라이언트 앱과 동일한 URL 공간에 있지 않음) 서버 쪽 앱에서 서비스를 구성하는 경우(예: 서버의 클라이언트 쪽 구성 요소 사전 렌더링 처리) 웹 API의 기본 주소로 URI를 설정합니다. 다음 예제에서는 웹 API https://localhost:5001의 기본 주소를 별도의 웹 API 앱이 실행되고 클라이언트 앱의 요청에 응답할 준비가 되는 위치로 설정합니다.

builder.Services.AddHttpClient("WebAPI", client => 
    client.BaseAddress = new Uri("https://localhost:5001"));

다음 구성 요소 코드에서:

  • IHttpClientFactory의 인스턴스는 명명된 HttpClient를 만듭니다.
  • 이름은 HttpClient 웹 API /forecast의 JSON 일기 예보 데이터에 대한 GET 요청을 발급하는 데 사용됩니다.
@inject IHttpClientFactory ClientFactory

...

@code {
    private Forecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        var client = ClientFactory.CreateClient("WebAPI");

        forecasts = await client.GetFromJsonAsync<Forecast[]>("forecast") ?? [];
    }
}

샘플 앱BlazorWebAppCallWebApi 구성 요소에 명명된 HttpClient 웹 API를 호출하는 방법을 CallTodoWebApiCsrNamedClient 보여 줍니다. 명명된 Microsoft HttpClientGraph 호출을 기반으로 하는 클라이언트 앱의 추가 작업 데모는 ASP.NET CoreBlazor WebAssembly에서 Graph API 사용을 참조하세요.

명명된 Microsoft HttpClientGraph 호출을 기반으로 하는 클라이언트 앱에서 작동하는 데모는 ASP.NET CoreBlazor WebAssembly에서 Graph API 사용을 참조하세요.

형식화된 HttpClient

형식화된 HttpClient는 앱의 기본값 또는 명명된 HttpClient 인스턴스를 사용하여 하나 이상의 웹 API 엔드포인트에서 데이터를 반환합니다.

참고 항목

형식화된 HttpClient를 사용하는 대신 IHttpClientFactory에서 명명된 HttpClient를 사용하는 것이 좋습니다. 자세한 내용은 NIHttpClientFactory가 포함된 명명된 HttpClient 섹션을 참조하세요.

앱에 Microsoft.Extensions.Http NuGet 패키지를 추가합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.

다음 예제에서는 웹 API의 JSON 날씨 예측 데이터에 대한 GET 요청을 실행합니다 /forecast.

ForecastHttpClient.cs:

using System.Net.Http.Json;

namespace BlazorSample.Client;

public class ForecastHttpClient(HttpClient http)
{
    public async Task<Forecast[]> GetForecastAsync() => 
        await http.GetFromJsonAsync<Forecast[]>("forecast") ?? [];
}

Program 클라이언트 프로젝트의 파일에서:

builder.Services.AddHttpClient<ForecastHttpClient>(client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

형식화된 클라이언트를 미리 렌더링된 클라이언트 쪽 구성 요소 Blazor Web App에서 사용하는 경우 이전 서비스 등록이 서버 프로젝트와 .Client 프로젝트 모두에 표시되어야 합니다. 서버 builder.HostEnvironment.BaseAddress 에서 웹 API의 기본 주소로 바뀝니다. 이 주소는 아래에 자세히 설명되어 있습니다.

앞의 예제에서는 클라이언트 쪽 앱의 기본 주소를 가져오고 일반적으로 호스트 페이지의 태그 href 값에서 <base> 파생되는 (IWebAssemblyHostEnvironment.BaseAddress)로 기본 주소를 builder.HostEnvironment.BaseAddress 설정합니다.

클라이언트의 자체 기본 주소를 사용하는 가장 일반적인 사용 사례는 다음과 같습니다.

  • WebAssembly/Auto 구성 요소 또는 WebAssembly의 클라이언트에서 실행되는 코드에서 동일한 호스트 주소의 Blazor Web App 서버 앱의 API로 웹 API를 호출하는 클라이언트 프로젝트(.Client)입니다.
  • 서버 프로젝트(Client)에 웹 API를 호출하는 호스트 Blazor WebAssembly 된 앱의 클라이언트 프로젝트(Server)입니다.

클라이언트의 기본 주소를 사용하는 가장 일반적인 사용 사례는 웹 API를 서버 프로젝트(Client)에 호출하는 호스트된 Blazor WebAssembly 앱의 클라이언트 프로젝트(Server)에 있습니다.

외부 웹 API를 호출하거나(클라이언트 앱과 동일한 URL 공간에 있지 않음) 서버 쪽 앱에서 서비스를 구성하는 경우(예: 서버의 클라이언트 쪽 구성 요소 사전 렌더링 처리) 웹 API의 기본 주소로 URI를 설정합니다. 다음 예제에서는 웹 API https://localhost:5001의 기본 주소를 별도의 웹 API 앱이 실행되고 클라이언트 앱의 요청에 응답할 준비가 되는 위치로 설정합니다.

builder.Services.AddHttpClient<ForecastHttpClient>(client => 
    client.BaseAddress = new Uri("https://localhost:5001"));

구성 요소는 형식화된 HttpClient를 삽입하여 웹 API를 호출합니다.

다음 구성 요소 코드에서:

  • 앞의 ForecastHttpClient 인스턴스가 삽입되어 형식화된 HttpClient를 만듭니다.
  • 형식화된 HttpClient는 웹 API에서 JSON 날씨 예측 데이터에 대한 GET 요청을 실행하는 데 사용됩니다.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await Http.GetForecastAsync();
    }
}

샘플 앱BlazorWebAppCallWebApi 구성 요소에 형식화된 HttpClient 웹 API를 호출하는 방법을 CallTodoWebApiCsrTypedClient 보여 줍니다. 구성 요소는 미리 렌더링된 CSR(클라이언트 쪽 렌더링)(InteractiveWebAssembly렌더링 모드) 채택하므로 형식화된 클라이언트 서비스 등록이 서버 프로젝트와 .Client 프로젝트 모두의 파일에 표시됩니다Program.

이 섹션의 지침은 인증 cookie을 사용하는 클라이언트 쪽 시나리오에 적용됩니다.

전달자 토큰 인증보다 더 안전한 것으로 간주되는 -based Authentication의 경우 cookie미리 구성된 HttpClient상태에서 호출 AddHttpMessageHandler 하여 각 웹 API 요청과 함께 자격 증명을 DelegatingHandler 보낼 수 cookie 있습니다. 처리기는 각 요청(예: 쿠키 또는 HTTP 인증 헤더)과 함께 원본 간 요청을 포함하여 자격 증명을 보내도록 브라우저에 권고하는 를 사용하여 구성 SetBrowserRequestCredentials BrowserRequestCredentials.Include합니다.

CookieHandler.cs:

public class CookieHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
        request.Headers.Add("X-Requested-With", ["XMLHttpRequest"]);

        return base.SendAsync(request, cancellationToken);
    }
}

파일에 CookieHandler 등록됩니다.Program

builder.Services.AddTransient<CookieHandler>();

메시지 처리기는 인증이 필요한 미리 구성된 HttpClient 모든 처리기에 추가됩니다.cookie

builder.Services.AddHttpClient(...)
    .AddHttpMessageHandler<CookieHandler>();

데모는 ASP.NET Core를 사용하여 보안 ASP.NET Core를 참조하세요Identity.Blazor WebAssembly

작성할 HttpRequestMessage때 브라우저 요청 자격 증명 및 헤더를 직접 설정합니다.

var requestMessage = new HttpRequestMessage() { ... };

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
requestMessage.Headers.Add("X-Requested-With", ["XMLHttpRequest"]);

Fetch API 요청 옵션이 있는 HttpClientHttpRequestMessage

이 섹션의 지침은 전달자 토큰 인증을 사용하는 클라이언트 쪽 시나리오에 적용됩니다.

HttpClient(API 설명서) 및 HttpRequestMessage를 사용하여 요청을 사용자 지정할 수 있습니다. 예를 들어, HTTP 메서드 및 요청 헤더를 지정할 수 있습니다. 다음 구성 요소는 웹 API 엔드포인트에 대한 POST 요청을 만들고 응답 본문을 표시합니다.

TodoRequest.razor:

@page "/todo-request"
@using System.Net.Http.Headers
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject HttpClient Http
@inject IAccessTokenProvider TokenProvider

<h1>ToDo Request</h1>

<h1>ToDo Request Example</h1>

<button @onclick="PostRequest">Submit POST request</button>

<p>Response body returned by the server:</p>

<p>@responseBody</p>

@code {
    private string? responseBody;

    private async Task PostRequest()
    {
        var requestMessage = new HttpRequestMessage()
        {
            Method = new HttpMethod("POST"),
            RequestUri = new Uri("https://localhost:10000/todoitems"),
            Content =
                JsonContent.Create(new TodoItem
                {
                    Name = "My New Todo Item",
                    IsComplete = false
                })
        };

        var tokenResult = await TokenProvider.RequestAccessToken();

        if (tokenResult.TryGetToken(out var token))
        {
            requestMessage.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", token.Value);

            requestMessage.Content.Headers.TryAddWithoutValidation(
                "x-custom-header", "value");

            var response = await Http.SendAsync(requestMessage);
            var responseStatusCode = response.StatusCode;

            responseBody = await response.Content.ReadAsStringAsync();
        }
    }

    public class TodoItem
    {
        public long Id { get; set; }
        public string? Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

Blazor'의 클라이언트 쪽 구현 HttpClient 에서는 Fetch API사용하고 확장 메서드 WebAssemblyHttpRequestMessageExtensions및 를 통해 HttpRequestMessage 기본 요청별 Fetch API 옵션을 구성합니다. 일반적인 SetBrowserRequestOption 확장 메서드를 사용하여 추가 옵션을 설정합니다. Blazor 기본 Fetch API는 요청 헤더를 직접 추가하거나 수정하지 않습니다. 브라우저와 같은 사용자 에이전트가 헤더와 상호 작용하는 방법에 대한 자세한 내용은 외부 사용자 에이전트 설명서 집합 및 기타 웹 리소스를 참조하세요.

HTTP 응답은 일반적으로 응답 콘텐츠에서 동기 읽기를 지원할 수 있도록 버퍼링됩니다. 응답 스트리밍을 지원하도록 설정하려면 요청에서 SetBrowserResponseStreamingEnabled 확장 메서드를 사용합니다.

원본 간 요청에 자격 증명을 포함하려면 SetBrowserRequestCredentials 확장 메서드를 사용합니다.

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Fetch API 옵션에 대한 자세한 내용은 MDN 웹 문서: WindowOrWorkerGlobalScope.fetch(): 매개 변수를 참조하세요.

오류 처리

개발자 코드에서 웹 API 응답 오류가 발생할 때 처리합니다. 예를 들어 GetFromJsonAsync에는 application/jsonContent-Type을 가진 웹 API의 JSON 응답이 필요합니다. 응답이 JSON 형식이 아닌 경우 콘텐츠 유효성 검사는 NotSupportedException을 throw합니다.

다음 예제에서는 날씨 예측 데이터 요청에 대한 URI 엔드포인트의 철자가 잘못되었습니다. URI는 WeatherForecast에 대한 것이어야 Forecast에서 e 문자가 누락된 WeatherForcast로 호출에 표시됩니다.

GetFromJsonAsync 호출에서는 JSON이 반환되어야 하지만, 웹 API는 text/htmlContent-Type을 사용하여 처리되지 않은 예외에 대한 HTML을 반환합니다. /WeatherForcast에 대한 경로를 찾을 수 없고 미들웨어에서 요청에 대한 페이지 또는 보기를 제공할 수 없기 때문에 처리되지 않은 예외가 발생합니다.

클라이언트의 OnInitializedAsync에서 응답 콘텐츠가 JSON이 아닌 것으로 확인되면 NotSupportedException이 throw됩니다. catch 블록에서 예외가 catch됩니다. 여기서 사용자 지정 논리는 오류를 기록하거나 사용자에게 친숙한 오류 메시지를 표시할 수 있습니다.

ReturnHTMLOnException.razor:

@page "/return-html-on-exception"
@using {PROJECT NAME}.Shared
@inject HttpClient Http

<h1>Fetch data but receive HTML on unhandled exception</h1>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <h2>Temperatures by Date</h2>

    <ul>
        @foreach (var forecast in forecasts)
        {
            <li>
                @forecast.Date.ToShortDateString():
                @forecast.TemperatureC &#8451;
                @forecast.TemperatureF &#8457;
            </li>
        }
    </ul>
}

<p>
    @exceptionMessage
</p>

@code {
    private WeatherForecast[]? forecasts;
    private string? exceptionMessage;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            // The URI endpoint "WeatherForecast" is misspelled on purpose on the 
            // next line. See the preceding text for more information.
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForcast");
        }
        catch (NotSupportedException exception)
        {
            exceptionMessage = exception.Message;
        }
    }
}

참고 항목

앞의 예제는 데모용입니다. 엔드포인트가 없거나 서버에서 처리되지 않은 예외가 발생한 경우에도 JSON을 반환하도록 웹 API를 구성할 수 있습니다.

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

교차 출처 리소스 공유(CORS)

브라우저 보안 때문에 웹 페이지에서 해당 웹 페이지를 제공한 도메인이 아닌 다른 도메인에 요청을 수행하는 것이 제한됩니다. 이러한 제한 사항을 동일 원본 정책이라고 합니다. 동일 원본 정책은 악성 사이트에서 다른 사이트의 중요한 데이터를 읽는 것을 제한합니다(차단하지는 않음). 브라우저에서 다른 원본이 있는 엔드포인트로 요청을 하려면 엔드포인트에서 CORS(원본 간 리소스 공유)를 사용하도록 설정해야 합니다.

서버 쪽 CORS에 대한 자세한 내용은 ASP.NET Core에서 CORS(원본 간 요청) 사용을 참조 하세요. 이 문서의 예제는 구성 요소 시나리오와 직접 Razor 관련이 없지만 이 문서는 일반적인 CORS 개념을 학습하는 데 유용합니다.

클라이언트 쪽 CORS 요청에 대한 자세한 내용은 ASP.NET Core Blazor WebAssembly 추가 보안 시나리오를 참조하세요.

위조 방지 지원

HTTP 요청에 위조 방지 지원을 추가하려면 헤더 컬렉션을 다음과 같이 RequestVerificationToken삽입 AntiforgeryStateProvider 하고 헤더 컬렉션에 추가 RequestToken 합니다.

@inject AntiforgeryStateProvider Antiforgery
private async Task OnSubmit()
{
    var antiforgery = Antiforgery.GetAntiforgeryToken();
    var request = new HttpRequestMessage(HttpMethod.Post, "action");
    request.Headers.Add("RequestVerificationToken", antiforgery.RequestToken);
    var response = await client.SendAsync(request);
    ...
}

자세한 내용은 ASP.NET Core Blazor 인증 및 권한 부여를 참조하세요.

웹 API 액세스 테스트를 위한 Blazor 프레임워크 구성 요소 예제

Firefox 브라우저 개발자와 같은 웹 API 백 엔드 앱을 직접 테스트하기 위해 다양한 네트워크 도구를 공개적으로 사용할 수 있습니다. Blazor 프레임워크의 참조 원본에는 테스트에 유용한 HttpClient 테스트 자산이 포함됩니다.

dotnet/aspnetcore GitHub 리포지토리의 HttpClientTest 자산

참고 항목

.NET 참조 원본의 설명서 링크는 일반적으로 다음 릴리스의 .NET을 위한 현재 개발을 나타내는 리포지토리의 기본 분기를 로드합니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags(분기 또는 태그 전환) 드롭다운 목록을 사용합니다. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.

추가 리소스

일반

초과 게시 공격 완화

웹 API는 대량 할당 공격이라고도 하는 초과 게시 공격에 취약할 수 있습니다. 악의적인 사용자가 렌더링된 양식의 일부가 아닌 속성에 대한 데이터를 처리하는 서버에 HTML 양식 POST를 발급하고 개발자가 사용자가 수정하도록 허용하지 않으려는 경우 오버포스트 공격이 발생합니다. "overposting"이라는 용어는 말 그대로 악의적인 사용자가 양식에 과도하게 POSTed되었음을 의미합니다.

오버포스트 공격을 완화하는 방법에 대한 지침은 자습서: ASP.NET Core를 사용하여 웹 API 만들기를 참조 하세요.

서버 쪽

클라이언트 쪽