다음을 통해 공유


ASP.NET Core Blazor 네비게이션

비고

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

경고

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

이 문서에서는 .에서 Blazor페이지 탐색을 트리거하고 처리하는 방법을 설명합니다. 사용자는 일반 HTML 링크를 사용하여 여러 페이지 사이를 탐색할 수 있지만 전체 Blazor 페이지 다시 로드를 방지하고 더 원활한 환경을 제공하기 위해 애플리케이션 내에서 탐색을 향상시킵니다. NavLink 구성 요소를 사용하여 링크가 현재 페이지와 일치할 때 자동으로 스타일을 적용하는 탐색 링크를 만듭니다. C# 코드에서 프로그래밍 탐색 및 URI 관리를 위해 NavigationManager 서비스를 사용하십시오.

이 문서에서는 .에서 Blazor페이지 탐색을 트리거하고 처리하는 방법을 설명합니다. NavLink 구성 요소를 사용하여 링크가 현재 페이지와 일치할 때 자동으로 스타일을 적용하는 탐색 링크를 만듭니다. 프로그램적 탐색 및 URI 관리를 위해 C# 코드에서 NavigationManager 서비스를 사용하세요.

중요합니다

이 문서의 코드 예제는 클래스와 구성 요소에서 삽입된 Navigation에 대해 호출된 NavigationManager의 메서드를 보여줍니다.

탐색 링크를 만드는 경우 HTML 하이퍼링크 요소(NavLink) 대신 <a> 구성 요소를 사용합니다. NavLink 구성 요소는 <a>가 현재 URL과 일치하는지 아닌지에 따라 active CSS 클래스를 전환한다는 점을 제외하고 href 요소처럼 동작합니다. active 클래스는 사용자가 표시되는 탐색 링크 중에서 활성 페이지를 파악하는 데 도움이 됩니다. 현재 경로가 NavLink.ActiveClass와 일치하는 경우, 필요에 따라 href에 CSS 클래스 이름을 할당하여 렌더링된 링크에 사용자 지정 CSS 클래스를 적용합니다.

NavMenu 구성 요소(NavMenu.razor)는 Blazor 프로젝트 템플릿으로 만든 Blazor 앱에서:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
        <span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
    </NavLink>
</div>
<div class="nav-item px-3">
    <NavLink class="nav-link" href="counter">
        <span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
    </NavLink>
</div>

앞의 예제에서 HomeNavLinkhref="" 홈 URL과 일치하며 앱의 기본 기본 경로(active)에서만 / CSS 클래스를 받습니다. 사용자가 Counter 구성 요소를 /counter에서 방문할 때 두 번째 NavLinkactive 클래스를 받습니다.

NavLinkMatch 요소의 Match 특성에 할당할 수 있는 다음 두 가지 <NavLink> 옵션이 있습니다.

  • NavLinkMatch.All: NavLink 현재 URL과 일치할 때 활성 상태이며 쿼리 문자열 및 조각을 무시합니다. 쿼리 문자열/조각에서 일치를 포함하려면 Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext 스위치를 true로 설정하세요.
  • NavLinkMatch.Prefix (기본값): NavLink 현재 URL의 접두사와 일치하는 경우 활성입니다.

사용자 지정 일치 논리를 채택하려면 서브클래스 NavLinkShouldMatch 메서드를 재정의합니다. true CSS 클래스를 적용하려는 경우 메서드에서 active 반환합니다.

public class CustomNavLink : NavLink
{
    protected override bool ShouldMatch(string currentUriAbsolute)
    {
        // Custom matching logic
    }
}

NavLinkMatch 요소의 Match 특성에 할당할 수 있는 다음 두 가지 <NavLink> 옵션이 있습니다.

추가 NavLink 구성 요소 특성이 렌더링된 앵커 태그로 전달됩니다. 다음 예제에서 NavLink 구성 요소는 target 특성을 포함합니다.

<NavLink href="example-page" target="_blank">Example page</NavLink>

다음 HTML 태그가 렌더링됩니다.

<a href="example-page" target="_blank">Example page</a>

경고

Blazor가 자식 콘텐츠를 렌더링하는 방식 때문에 NavLink 루프 내에서 for 구성 요소를 렌더링하려면 NavLink(자식) 구성 요소 콘텐츠에서 증분 루프 변수를 사용할 경우 로컬 인덱스 변수가 필요합니다.

@for (int c = 1; c < 4; c++)
{
    var ct = c;
    <li ...>
        <NavLink ...>
            <span ...></span> Product #@ct
        </NavLink>
    </li>
}

이 시나리오에서 인덱스 변수를 사용하는 것은 구성 요소뿐 아니라 자식 콘텐츠에서 루프 변수를 사용하는 NavLink 자식 구성 요소의 요구 사항입니다.

또는 foreach을 활용하여 Enumerable.Range 루프를 사용할 수 있습니다.

@foreach (var c in Enumerable.Range(1, 3))
{
    <li ...>
        <NavLink ...>
            <span ...></span> Product #@c
        </NavLink>
    </li>
}

URI 및 탐색 상태 도우미

NavigationManager를 사용하여 C# 코드로 URI와 탐색을 관리할 수 있습니다. NavigationManager는 다음 표에 나와 있는 이벤트와 메서드를 제공합니다.

회원 Description
Uri 현재 절대 URI를 가져옵니다.
BaseUri 절대 URI를 생성하기 위해 상대 URI 경로 앞에 추가할 수 있는 기본 URI(후행 슬래시 포함)를 가져옵니다. 일반적으로 BaseUri는 문서의 href 요소에 있는 <base> 속성(<head> 콘텐츠의 위치)과 일치합니다.
NavigateTo 지정한 URI로 이동합니다. forceLoadfalse인 경우
  • 그리고 향상된 탐색은 현재 URL에서 사용할 수 있습니다. Blazor'의 향상된 탐색이 활성화됩니다.
  • 그렇지 않으면 Blazor 요청된 URL에 대한 전체 페이지 다시 로드를 수행합니다.
forceLoadtrue인 경우
  • 클라이언트 쪽 라우팅이 무시됩니다.
  • URI가 클라이언트 쪽 대화형 라우터에서 일반적으로 처리되는지 여부에 관계없이 브라우저는 서버에서 새 페이지를 로드해야 합니다.

자세한 내용은 향상된 탐색 및 양식 처리 섹션을 참조 하세요 .

replacetrue이면 새 URI를 기록 스택에 푸시하는 대신 브라우저 기록의 현재 URI가 바뀝니다.

LocationChanged 탐색 위치가 변경될 때 발생하는 이벤트. 자세한 내용은 위치 변경 섹션을 참조하세요.
NotFound 요청된 리소스를 찾을 수 없는 시나리오를 처리하기 위해 호출됩니다. 자세한 내용은 찾을 수 없음 응답 섹션을 참조하세요.
ToAbsoluteUri 상대 URI를 절대 URI로 변환합니다.
ToBaseRelativePath 앱의 기본 URI를 기준으로 절대 URI를 기본 URI의 접두사에 상대적인 URI로 변환합니다. 예를 들어, 기본 URI 접두사를 기준으로 URI 생성 섹션을 참조하세요.
RegisterLocationChangingHandler 들어오는 탐색 이벤트를 처리하기 위해 처리기를 등록합니다. NavigateTo를 호출하면 항상 처리기가 호출됩니다.
GetUriWithQueryParameter 단일 매개 변수의 추가, 업데이트 또는 제거를 통해 NavigationManager.Uri를 업데이트하여 생성된 URI를 반환합니다. 자세한 내용은 쿼리 문자열 섹션을 참조하세요.
회원 Description
Uri 현재 절대 URI를 가져옵니다.
BaseUri 절대 URI를 생성하기 위해 상대 URI 경로 앞에 추가할 수 있는 기본 URI(후행 슬래시 포함)를 가져옵니다. 일반적으로 BaseUri는 문서의 href 요소에 있는 <base> 속성(<head> 콘텐츠의 위치)과 일치합니다.
NavigateTo 지정한 URI로 이동합니다. forceLoadfalse인 경우
  • 그리고 향상된 탐색은 현재 URL에서 사용할 수 있습니다. Blazor'의 향상된 탐색이 활성화됩니다.
  • 그렇지 않으면 Blazor 요청된 URL에 대한 전체 페이지 다시 로드를 수행합니다.
forceLoadtrue인 경우
  • 클라이언트 쪽 라우팅이 무시됩니다.
  • URI가 클라이언트 쪽 대화형 라우터에서 일반적으로 처리되는지 여부에 관계없이 브라우저는 서버에서 새 페이지를 로드해야 합니다.

자세한 내용은 향상된 탐색 및 양식 처리 섹션을 참조 하세요 .

replacetrue이면 새 URI를 기록 스택에 푸시하는 대신 브라우저 기록의 현재 URI가 바뀝니다.

LocationChanged 탐색 위치가 변경될 때 발생하는 이벤트. 자세한 내용은 위치 변경 섹션을 참조하세요.
ToAbsoluteUri 상대 URI를 절대 URI로 변환합니다.
ToBaseRelativePath 앱의 기본 URI를 기준으로 절대 URI를 기본 URI의 접두사에 상대적인 URI로 변환합니다. 예를 들어, 기본 URI 접두사를 기준으로 URI 생성 섹션을 참조하세요.
RegisterLocationChangingHandler 들어오는 탐색 이벤트를 처리하기 위해 처리기를 등록합니다. NavigateTo를 호출하면 항상 처리기가 호출됩니다.
GetUriWithQueryParameter 단일 매개 변수의 추가, 업데이트 또는 제거를 통해 NavigationManager.Uri를 업데이트하여 생성된 URI를 반환합니다. 자세한 내용은 쿼리 문자열 섹션을 참조하세요.
회원 Description
Uri 현재 절대 URI를 가져옵니다.
BaseUri 절대 URI를 생성하기 위해 상대 URI 경로 앞에 추가할 수 있는 기본 URI(후행 슬래시 포함)를 가져옵니다. 일반적으로 BaseUri는 문서의 href 요소에 있는 <base> 속성(<head> 콘텐츠의 위치)과 일치합니다.
NavigateTo 지정한 URI로 이동합니다. forceLoadtrue인 경우
  • 클라이언트 쪽 라우팅이 무시됩니다.
  • 클라이언트 쪽 라우터에서 URI를 정상적으로 처리했는지와 상관없이 브라우저에서 서버의 새 페이지를 강제로 로드합니다.
replacetrue이면 새 URI를 기록 스택에 푸시하는 대신 브라우저 기록의 현재 URI가 바뀝니다.
LocationChanged 탐색 위치가 변경될 때 발생하는 이벤트. 자세한 내용은 위치 변경 섹션을 참조하세요.
ToAbsoluteUri 상대 URI를 절대 URI로 변환합니다.
ToBaseRelativePath 앱의 기본 URI를 기준으로 절대 URI를 기본 URI의 접두사에 상대적인 URI로 변환합니다. 예를 들어, 기본 URI 접두사를 기준으로 URI 생성 섹션을 참조하세요.
RegisterLocationChangingHandler 들어오는 탐색 이벤트를 처리하기 위해 처리기를 등록합니다. NavigateTo를 호출하면 항상 처리기가 호출됩니다.
GetUriWithQueryParameter 단일 매개 변수의 추가, 업데이트 또는 제거를 통해 NavigationManager.Uri를 업데이트하여 생성된 URI를 반환합니다. 자세한 내용은 쿼리 문자열 섹션을 참조하세요.
회원 Description
Uri 현재 절대 URI를 가져옵니다.
BaseUri 절대 URI를 생성하기 위해 상대 URI 경로 앞에 추가할 수 있는 기본 URI(후행 슬래시 포함)를 가져옵니다. 일반적으로 BaseUri는 문서의 href 요소에 있는 <base> 속성(<head> 콘텐츠의 위치)과 일치합니다.
NavigateTo 지정한 URI로 이동합니다. forceLoadtrue인 경우
  • 클라이언트 쪽 라우팅이 무시됩니다.
  • 클라이언트 쪽 라우터에서 URI를 정상적으로 처리했는지와 상관없이 브라우저에서 서버의 새 페이지를 강제로 로드합니다.
replacetrue이면 새 URI를 기록 스택에 푸시하는 대신 브라우저 기록의 현재 URI가 바뀝니다.
LocationChanged 탐색 위치가 변경될 때 발생하는 이벤트. 자세한 내용은 위치 변경 섹션을 참조하세요.
ToAbsoluteUri 상대 URI를 절대 URI로 변환합니다.
ToBaseRelativePath 앱의 기본 URI를 기준으로 절대 URI를 기본 URI의 접두사에 상대적인 URI로 변환합니다. 예를 들어, 기본 URI 접두사를 기준으로 URI 생성 섹션을 참조하세요.
GetUriWithQueryParameter 단일 매개 변수의 추가, 업데이트 또는 제거를 통해 NavigationManager.Uri를 업데이트하여 생성된 URI를 반환합니다. 자세한 내용은 쿼리 문자열 섹션을 참조하세요.
회원 Description
Uri 현재 절대 URI를 가져옵니다.
BaseUri 절대 URI를 생성하기 위해 상대 URI 경로 앞에 추가할 수 있는 기본 URI(후행 슬래시 포함)를 가져옵니다. 일반적으로 BaseUri는 문서의 href 요소에 있는 <base> 속성(<head> 콘텐츠의 위치)과 일치합니다.
NavigateTo 지정한 URI로 이동합니다. forceLoadtrue인 경우
  • 클라이언트 쪽 라우팅이 무시됩니다.
  • 클라이언트 쪽 라우터에서 URI를 정상적으로 처리했는지와 상관없이 브라우저에서 서버의 새 페이지를 강제로 로드합니다.
LocationChanged 탐색 위치가 변경될 때 발생하는 이벤트.
ToAbsoluteUri 상대 URI를 절대 URI로 변환합니다.
ToBaseRelativePath 앱의 기본 URI를 기준으로 절대 URI를 기본 URI의 접두사에 상대적인 URI로 변환합니다. 예를 들어, 기본 URI 접두사를 기준으로 URI 생성 섹션을 참조하세요.

위치 변경

LocationChanged 이벤트의 경우 LocationChangedEventArgs는 탐색 이벤트에 대해 다음 정보를 제공합니다.

다음 구성 요소:

  • Counter를 사용하여 단추를 선택하면 앱의 Counter.razor 구성 요소(NavigateTo)로 이동합니다.
  • NavigationManager.LocationChanged를 구독하여 위치 변경 이벤트를 처리합니다.
    • HandleLocationChanged 메서드는 프레임워크에서 Dispose를 호출할 때 언후크됩니다. 메서드를 언후크하면 구성 요소의 가비지 수집이 가능하게 됩니다.

    • 로거 구현은 단추를 선택할 때 다음 정보를 기록합니다.

      BlazorSample.Pages.Navigate: Information: URL of new location: https://localhost:{PORT}/counter

Navigate.razor:

@page "/navigate"
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation

<h1>Navigate Example</h1>

<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
    Navigate to the Counter component
</button>

@code {
    private void NavigateToCounterComponent() => Navigation.NavigateTo("counter");

    protected override void OnInitialized() => 
        Navigation.LocationChanged += HandleLocationChanged;

    private void HandleLocationChanged(object? sender, LocationChangedEventArgs e) => 
        Logger.LogInformation("URL of new location: {Location}", e.Location);

    public void Dispose() => Navigation.LocationChanged -= HandleLocationChanged;
}

구성 요소 삭제에 대한 자세한 내용은 ASP.NET Core Razor 구성 요소 삭제참조하세요.

정적 서버 쪽 렌더링 중 리디렉션(정적 SSR) NavigationManager 의 경우 프레임워크에서 NavigationException 캡처되는 throw에 의존하여 오류를 리디렉션으로 변환합니다. 호출 NavigateTo 후에 존재하는 코드는 호출되지 않습니다. Visual Studio를 사용하는 경우 디버거가 예외를 중단하므로 이후 리디렉션을 위해 디버거가 중지되지 않도록 Visual Studio UI에서 이 예외 유형이 사용자 처리될 때 중단 확인란의 선택을 취소해야 합니다.

앱의 프로젝트 파일에서 MSBuild 속성 집합을 <BlazorDisableThrowNavigationException> 사용하여 true 더 이상 옵트인(opt-in)하여 더 이상 옵트인(opt-in)할 수 있습니다NavigationException. 또한 호출 NavigateTo 후 코드는 이전에 실행되지 않았을 때 실행됩니다. 이 동작은 .NET 10 이상 Blazor Web App 프로젝트 템플릿에서 기본적으로 사용하도록 설정됩니다.

<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>

비고

.NET 10 이상에서는 MSBuild 속성을 앱의 프로젝트 파일로 설정 NavigationException 하여 throw <BlazorDisableThrowNavigationException> 하지 않도록 옵트인할 true 수 있습니다. 새 MSBuild 속성 및 동작을 활용하려면 앱을 .NET 10 이상으로 업그레이드합니다.

응답을 찾을 수 없음

NavigationManager 에서는 NotFound 정적 서버 쪽 렌더링(정적 SSR) 또는 전역 대화형 렌더링 중에 요청된 리소스를 찾을 수 없는 시나리오를 처리하는 메서드를 제공합니다.

  • 정적 SSR: 호출 NavigationManager.NotFound 은 HTTP 상태 코드를 404로 설정합니다.

  • 대화형 렌더링: 라우터(Blazor)에게 찾을 수 없는 콘텐츠를 렌더링하도록 신호를 Router 보냅니다.

  • 스트리밍 렌더링: 향상된 탐색 이 활성화된 경우 스트리밍 렌더링 은 페이지를 다시 로드하지 않고도 찾을 수 없는 콘텐츠를 렌더링합니다. 향상된 탐색이 차단되면 프레임워크는 페이지 새로 고침을 사용하여 찾을 수 없는 콘텐츠로 리디렉션됩니다.

비고

다음 설명에서는 찾을 수 없는 Razor 구성 요소를 구성 요소의 Router 매개 변수에 NotFoundPage 할당할 수 있다고 설명합니다. 매개 변수는 함께 NavigationManager.NotFound 작동하며 이 섹션의 뒷부분에 자세히 설명되어 있습니다.

스트리밍 렌더링은 할당() 또는 NotFoundPage(NotFoundPage="...")과 같은 UseStatusCodePagesWithReExecute 경로가 있는 구성 요소만 렌더링할 수 있습니다. DefaultNotFound 404 콘텐츠("Not found일반 텍스트")에는 경로가 없으므로 스트리밍 렌더링 중에 사용할 수 없습니다.

비고

찾을 수 없는 렌더링 조각(<NotFound>...</NotFound>)은 .NET 10 이상에서 지원되지 않습니다.

NavigationManager.NotFound 콘텐츠 렌더링은 응답이 시작되었는지 여부에 관계없이(순서대로) 다음을 사용합니다.

  • 설정된 경우 NotFoundEventArgs.Path 할당된 페이지의 내용을 렌더링합니다.
  • 설정된 경우 Router.NotFoundPage 할당된 페이지를 렌더링합니다.
  • 구성된 경우 상태 코드 페이지를 다시 실행하는 미들웨어 페이지입니다.
  • 이전 방법을 채택하지 않으면 아무 작업도 수행되지 않습니다.

상태 코드 페이지 다시 실행 미들웨어는 브라우저의 주소 표시줄에 잘못된 URL이 입력되거나 앱에 엔드포인트가 없는 링크가 선택되는 경우와 같은 브라우저 기반 주소 라우팅 문제를 우선적으로 처리합니다.

구성 요소가 정적으로 렌더링되고(정적 SSR) NavigationManager.NotFound 호출되면 응답에 404 상태 코드가 설정됩니다.

@page "/render-not-found-ssr"
@inject NavigationManager Navigation

@code {
    protected override void OnInitialized()
    {
        Navigation.NotFound();
    }
}

글로벌 대화형 렌더링에 찾을 수 없는 콘텐츠를 제공하려면 찾을 수 없는 페이지(Razor 구성 요소)를 사용합니다.

비고

프로젝트 템플릿에는 Blazor 페이지가 NotFound.razor 포함됩니다. 이 페이지는 호출할 때마다 NavigationManager.NotFound 자동으로 렌더링되므로 일관된 사용자 환경으로 누락된 경로를 처리할 수 있습니다.

Pages/NotFound.razor:

@page "/not-found"
@layout MainLayout

<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>

NotFound 구성 요소는 라우터의 NotFoundPage 매개 변수에 할당됩니다. NotFoundPage는 Blazor 미들웨어가 아닌 것도 포함하여 상태 코드 페이지 재실행 미들웨어에서 사용할 수 있는 라우팅을 지원합니다.

다음 예제에서는 이전 NotFound 구성 요소가 앱의 Pages 폴더에 있고 매개 변수에 NotFoundPage 전달됩니다.

<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>

구성 요소가 전역 대화형 렌더링 모드로 렌더링되면 호출 NavigationManager.NotFound 은 라우터에 Blazor 구성 요소를 렌더링 NotFound 하도록 신호를 보냅니다.

@page "/render-not-found-interactive"
@inject NavigationManager Navigation

@if (RendererInfo.IsInteractive)
{
    <button @onclick="TriggerNotFound">Trigger Not Found</button>
}

@code {
    private void TriggerNotFound()
    {
        Navigation.NotFound();
    }
}

OnNotFound가 호출될 때 알림을 위해 NavigationManager.NotFound 이벤트를 사용할 수 있습니다. 이 이벤트는 NavigationManager.NotFound가 호출될 때만 발생하며, 404 응답에 대해서는 발생하지 않습니다. 예를 들어, HttpContextAccessor.HttpContext.Response.StatusCode을(를) 404로 설정해도 NavigationManager.NotFound/OnNotFound이(가) 트리거되지 않습니다.

사용자 지정 라우터를 구현하는 앱도 사용할 NavigationManager.NotFound수 있습니다. 사용자 지정 라우터는 응답 상태에 따라 두 소스에서 찾을 수 없는 콘텐츠를 렌더링할 수 있습니다.

  • 응답 상태에 관계없이 페이지의 다시 실행 경로는 UseStatusCodePagesWithReExecute로 전달하여 활용할 수 있습니다.

    app.UseStatusCodePagesWithReExecute(
        "/not-found", createScopeForStatusCodePages: true);
    
  • 응답이 시작되면 NotFoundEventArgs.Path 라우터에서 구독하여 OnNotFoundEvent 사용할 수 있습니다.

    @code {
        [CascadingParameter]
        public HttpContext? HttpContext { get; set; }
    
        private void OnNotFoundEvent(object sender, NotFoundEventArgs e)
        {
            // Only execute the logic if HTTP response has started,
            // because setting NotFoundEventArgs.Path blocks re-execution
            if (HttpContext?.Response.HasStarted == false)
            {
                return;
            }
    
            var type = typeof(CustomNotFoundPage);
            var routeAttributes = type.GetCustomAttributes<RouteAttribute>(inherit: true);
    
            if (routeAttributes.Length == 0)
            {
                throw new InvalidOperationException($"The type {type.FullName} " +
                    $"doesn't have a {nameof(RouteAttribute)} applied.");
            }
    
            var routeAttribute = (RouteAttribute)routeAttributes[0];
    
            if (routeAttribute.Template != null)
            {
                e.Path = routeAttribute.Template;
            }
        }
    }
    

대화형 인터랙티브 SSR(인터랙티브 서버 사이드 렌더링)을 채택하는 구성 요소에 대한 다음 예제에서는 OnNotFound이 호출되는 위치에 따라 사용자 지정 콘텐츠가 렌더링됩니다. 구성 요소 초기화에서 동영상을 찾을 수 없을 때 다음 Movie 구성 요소에 의해 이벤트가 트리거되는 경우 사용자 지정 메시지는 요청된 동영상을 찾을 수 없음을 나타냅니다. 다음 예제의 구성 요소에 의해 User 이벤트가 트리거되는 경우 다른 메시지는 사용자를 찾을 수 없음을 나타냅니다.

다음 NotFoundContext 서비스는 구성 요소에서 콘텐츠를 찾을 수 없는 경우의 컨텍스트 및 메시지를 관리합니다.

NotFoundContext.cs:

public class NotFoundContext
{
    public string? Heading { get; private set; }
    public string? Message { get; private set; }

    public void UpdateContext(string heading, string message)
    {
        Heading = heading;
        Message = message;
    }
}

서비스는 서버 쪽 Program 파일에 등록됩니다.

builder.Services.AddScoped<NotFoundContext>();

페이지는 NotFound를 삽입하고 NotFoundContext를 표시하여 제목과 메시지를 보여줍니다.

Pages/NotFound.razor:

@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext

<h3>@NotFoundContext.Heading</h3>
<div>
    <p>@NotFoundContext.Message</p>
</div>

Routes 구성 요소는 NotFoundPage 매개 변수를 통해 NotFound 구성 요소를 "찾을 수 없는 페이지"로 설정합니다.

<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
    ...
</Router>

다음 예제 구성 요소에서:

  • NotFoundContext 서비스가 NavigationManager 서비스와 함께 삽입됩니다.
  • OnInitializedAsync에서 HandleNotFound 이벤트에 할당된 이벤트 처리기가 OnNotFound입니다. HandleNotFoundNotFound 구성 요소에서 찾을 수 없는 콘텐츠에 대한 제목과 메시지를 설정하기 위해 NotFoundContext.UpdateContext를 호출합니다.
  • 구성 요소는 일반적으로 경로 매개 변수의 ID를 사용하여 데이터베이스와 같은 데이터 저장소에서 영화 또는 사용자를 가져옵니다. 다음 예제에서는 엔터티를 찾을 수 없을 때 발생하는 작업을 시뮬레이션하기 위해 엔터티가 반환되지 않습니다(null).
  • OnInitializedAsync에 엔터티가 반환되지 않으면, NavigationManager.NotFound가 호출되어 OnNotFound 이벤트와 HandleNotFound 이벤트 처리기가 트리거됩니다. 찾을 수 없는 콘텐츠는 라우터에 의해 표시됩니다.
  • 구성 요소가 삭제될 때 HandleNotFound 메서드는 IDisposable.Dispose에서 언후킹됩니다.

Movie 구성 요소(Movie.razor):

@page "/movie/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext

<div>
    No matter what ID is used, no matching movie is returned
    from the call to GetMovie().
</div>

@code {
    [Parameter]
    public int Id { get; set; }

    protected override async Task OnInitializedAsync()
    {
        NavigationManager.OnNotFound += HandleNotFound;

        var movie = await GetMovie(Id);

        if (movie == null)
        {
            NavigationManager.NotFound();
        }
    }

    private void HandleNotFound(object? sender, NotFoundEventArgs e)
    {
        NotFoundContext.UpdateContext("Movie Not Found",
            "Sorry! The requested movie wasn't found.");
    }

    private async Task<MovieItem[]?> GetMovie(int id)
    {
        // Simulate no movie with matching id found
        return await Task.FromResult<MovieItem[]?>(null);
    }

    void IDisposable.Dispose()
    {
        NavigationManager.OnNotFound -= HandleNotFound;
    }

    public class MovieItem
    {
        public int Id { get; set; }
        public string? Title { get; set; }
    }
}

User 구성 요소(User.razor):

@page "/user/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext

<div>
    No matter what ID is used, no matching user is returned
    from the call to GetUser().
</div>

@code {
    [Parameter]
    public int Id { get; set; }

    protected override async Task OnInitializedAsync()
    {
        NavigationManager.OnNotFound += HandleNotFound;

        var user = await GetUser(Id);

        if (user == null)
        {
            NavigationManager.NotFound();
        }
    }

    private void HandleNotFound(object? sender, NotFoundEventArgs e)
    {
        NotFoundContext.UpdateContext("User Not Found",
            "Sorry! The requested user wasn't found.");
    }

    private async Task<UserItem[]?> GetUser(int id)
    {
        // Simulate no user with matching id found
        return await Task.FromResult<UserItem[]?>(null);
    }

    void IDisposable.Dispose()
    {
        NavigationManager.OnNotFound -= HandleNotFound;
    }

    public class UserItem
    {
        public int Id { get; set; }
        public string? Name { get; set; }
    }
}

테스트 앱을 사용하여 로컬 데모에서 이전 구성 요소에 도달하려면 NavMenu 구성 요소에 항목을 생성하여 NavMenu.razor, MovieUser 구성 요소에 도달하십시오. 다음 예제에서 경로 매개 변수로 전달되는 엔터티 ID는 실제로 구성 요소에서 사용되지 않으므로 영향을 주지 않는 모의 값으로, 영화나 사용자를 찾지 못하는 것을 시뮬레이션합니다.

NavMenu.razor의 경우

<div class="nav-item px-3">
    <NavLink class="nav-link" href="movie/1">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Movie
    </NavLink>
</div>

<div class="nav-item px-3">
    <NavLink class="nav-link" href="user/2">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User
    </NavLink>
</div>

향상된 탐색 및 양식 처리

이 섹션은 s에 Blazor Web App적용됩니다.

Blazor Web Apps는 페이지 탐색 및 양식 처리 요청에 대한 두 가지 유형의 라우팅을 수행할 수 있습니다.

  • 일반 탐색(문서 간 탐색): 요청 URL에 대해 전체 페이지 다시 로드가 트리거됩니다.
  • 향상된 탐색(동일한 문서 탐색): Blazor 요청을 가로채서 대신 fetch 요청을 수행합니다. Blazor 그런 다음, 응답 콘텐츠를 페이지의 DOM에 패치합니다. Blazor'의 향상된 탐색 및 양식 처리는 전체 페이지 다시 로드의 필요성을 방지하고 페이지 상태를 더 많이 유지하므로 일반적으로 페이지에서 사용자의 스크롤 위치를 잃지 않고 페이지가 더 빠르게 로드됩니다.

다음과 같은 경우 향상된 탐색을 사용할 수 있습니다.

  • Blazor Web App 스크립트(blazor.web.js)가 사용되며, Blazor Server 스크립트(blazor.server.js)나 Blazor WebAssembly 스크립트(blazor.webassembly.js)는 사용되지 않습니다.
  • 이 기능은 명시적으로 사용하지 않도록 설정되지 않았습니다.
  • 대상 URL은 앱의 기본 경로인 내부 기본 URI 공간 내에 있으며, 페이지 링크에 data-enhance-nav 특성이 false로 설정되지 않았습니다.

서버 쪽 라우팅 및 향상된 탐색을 사용하는 경우 위치 변경 처리기는 대화형 런타임에서 시작된 프로그래밍 방식 탐색에 대해서만 호출됩니다. 이후 릴리스에서는 링크 팔로우와 같은 추가 유형의 탐색이 위치 변경 처리기를 호출할 수도 있습니다.

향상된 탐색이 LocationChanged 발생하면 대화형 서버 및 WebAssembly 런타임에 등록된 이벤트 처리기가 일반적으로 호출됩니다. 위치 변경 처리기가 향상된 내비게이션을 가로채지 못할 수 있는 경우가 있습니다. 예를 들어 사용자가 대화형 런타임을 사용할 수 있게 되기 전에 다른 페이지로 전환할 수 있습니다. 따라서 처리기 실행이 보장되지 않으므로 앱 논리가 위치 변경 처리기를 호출하는 데 의존하지 않는 것이 중요합니다.

호출 NavigateTo할 때:

  • forceLoad이 경우 false 기본값은 다음과 같습니다.
    • 그리고 향상된 탐색은 현재 URL에서 사용할 수 있습니다. Blazor'의 향상된 탐색이 활성화됩니다.
    • 그렇지 않으면 Blazor 요청된 URL에 대한 전체 페이지 다시 로드를 수행합니다.
  • forceLoadtrue인 경우: Blazor는 향상된 탐색을 사용할 수 있는지 여부에 관계없이 요청된 URL에 대해 전체 페이지를 다시 로드합니다.

사용 가능한 경우 항상 향상된 탐색을 수행하는 호출 NavigationManager.Refresh(bool forceLoad = false)을 통해 현재 페이지를 새로 고칠 수 있습니다. 향상된 탐색을 사용할 수 Blazor 없는 경우 전체 페이지 다시 로드를 수행합니다.

Navigation.Refresh();

trueforceLoad 매개 변수로 전달하여 향상된 탐색이 가능하더라도 항상 전체 페이지가 다시 로드되도록 합니다.

Navigation.Refresh(true);

향상된 탐색은 기본적으로 사용하도록 설정되지만 HTML 특성을 사용하여 data-enhance-nav 계층적으로 그리고 링크별로 제어할 수 있습니다.

다음 예제에서는 향상된 탐색을 사용하지 않도록 설정합니다.

<a href="redirect" data-enhance-nav="false">
    GET without enhanced navigation
</a>
<ul data-enhance-nav="false">
    <li>
        <a href="redirect">GET without enhanced navigation</a>
    </li>
    <li>
        <a href="redirect-2">GET without enhanced navigation</a>
    </li>
</ul>

대상이 비 엔드Blazor 포인트인 경우 향상된 탐색이 적용되지 않으며 클라이언트 쪽 JavaScript가 전체 페이지 로드로 다시 시도합니다. 이렇게 하면 기존 페이지에 패치를 적용해서는 안 되는 외부 페이지에 대한 프레임워크의 혼동이 발생하지 않습니다.

향상된 양식 처리를 사용하도록 설정하려면 양식에 Enhance 매개 변수 EditForm 를 추가하거나 data-enhance HTML 양식(<form>)에 특성을 추가합니다.

<EditForm ... Enhance ...>
    ...
</EditForm>
<form ... data-enhance ...>
    ...
</form>

향상된 양식 처리는 계층 구조가 아니며 자식 양식으로 전달되지 않습니다.

지원되지 않음: 양식의 상위 요소에 대해 향상된 탐색을 설정하여 양식에 대해 향상된 탐색을 사용하도록 설정할 수 없습니다.

<div ... data-enhance ...>
    <form ...>
        <!-- NOT enhanced -->
    </form>
</div>

향상된 양식 게시물은 Blazor 엔드포인트와만 작동합니다. 비-Blazor 엔드포인트에 향상된 양식을 게시하면 오류가 발생합니다.

향상된 탐색을 사용하지 않도록 설정하려면 다음을 수행합니다.

  • EditForm의 경우, 폼 요소에서 매개변수 Enhance를 제거하거나, false: Enhance="false"로 설정하십시오.
  • HTML<form>의 경우, 양식 요소에서 data-enhance 속성을 제거하거나, falsedata-enhance="false"로 설정하세요.

Blazor업데이트된 콘텐츠가 서버 렌더링의 일부가 아닌 경우 향상된 탐색 및 양식 전달을 통해 DOM에 대한 동적 변경 내용을 실행 취소할 수 있습니다. 요소의 콘텐츠를 유지하려면 특성을 사용합니다 data-permanent .

다음 예제에서는 페이지가 로드되면 요소의 <div> 콘텐츠가 스크립트에 의해 동적으로 업데이트됩니다.

<div data-permanent>
    ...
</div>

클라이언트에서 시작되면 Blazor 이벤트를 사용하여 enhancedload 향상된 페이지 업데이트를 수신 대기할 수 있습니다. 이렇게 하면 향상된 페이지 업데이트로 실행 취소되었을 수 있는 변경 내용을 DOM에 다시 적용할 수 있습니다.

Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));

향상된 탐색 및 양식 처리를 전역적으로 사용하지 않도록 설정하려면 ASP.NET Core Blazor 시작을 참조하세요.

정적 서버 쪽 렌더링(정적 SSR)을 사용하는 경우, JavaScript를 로드할 때 특별한 주의가 필요한 강화된 내비게이션입니다. 자세한 내용은 ASP.NET Core JavaScript의 정적 서버 쪽 렌더링(정적 SSR)을 참조하세요.

기본 URI 접두사를 기준으로 URI 생성

앱의 기본 URI를 기준으로, ToBaseRelativePath는 절대 URI를 기본 URI 접두사가 적용된 상대 URI로 변환합니다.

다음 예시를 참조하세요.

try
{
    baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
    ...
}

앱의 기본 URI인 https://localhost:8000경우 다음 결과를 얻습니다.

  • https://localhost:8000/segmentinputURI에서 baseRelativePathsegment 결과로 이어집니다.
  • https://localhost:8000/segment1/segment2inputURI에서 baseRelativePathsegment1/segment2 결과로 이어집니다.

앱의 기본 URI가 inputURI의 기본 URI와 일치하지 않으면 ArgumentException가 발생합니다.

https://localhost:8001/segmentinputURI에 전달하면 다음 예외가 발생합니다.

System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'

NavigationManager는 브라우저 기록 API를 사용하여 앱에서 수행한 각 위치 변경과 관련된 탐색 기록 상태를 유지 관리합니다. 기록 상태를 유지 관리하는 것은 외부 ID 공급자를 사용하여 사용자를 인증하는 경우와 같은 외부 리디렉션 시나리오에서 특히 유용합니다. 자세한 내용은 탐색 옵션 섹션을 참조하세요.

NavigationOptionsNavigateTo에 전달하여 다음 동작을 제어합니다.

  • ForceLoad: 클라이언트 쪽 라우팅을 우회하고 URI가 클라이언트 쪽 라우터에서 처리되는지 여부에 관계없이 브라우저가 서버에서 새 페이지를 로드하도록 합니다. 기본값은 false입니다.
  • ReplaceHistoryEntry: 기록 스택의 현재 항목을 바꿉니다. false인 경우, 새 항목을 기록 스택에 추가합니다. 기본값은 false입니다.
  • HistoryEntryState: 기록 항목에 추가할 상태를 가져오거나 설정합니다.
Navigation.NavigateTo("/path", new NavigationOptions
{
    HistoryEntryState = "Navigation state"
});

위치 변경을 처리하는 동안 대상 기록 항목과 연관된 상태를 가져오는 방법에 대한 자세한 내용은 위치 변경 처리/방지 섹션을 참조하세요.

쿼리 문자열

[SupplyParameterFromQuery] 특성을 사용하여 구성 요소 매개 변수가 쿼리 문자열에서 제공되도록 지정합니다.

속성을 속성과 함께 사용하여 라우팅 가능한 구성 요소의 매개 변수가 쿼리 문자열에서 제공되도록 지정합니다.

비고

구성 요소 매개 변수는 @page 지시문을 사용하여 라우팅 가능한 구성 요소에서만 쿼리 매개 변수 값을 받을 수 있습니다.

하향식 정보 흐름을 전복하지 않고 프레임워크와 앱에서 매개 변수 처리 순서를 명확하게 하기 위해 라우팅 가능한 구성 요소만 쿼리 매개 변수를 직접 받습니다. 이 디자인은 특정 매개 변수 처리 순서로 작성된 앱 코드의 미묘한 버그를 방지합니다. 라우팅할 수 없는 구성 요소에 쿼리 매개 변수 값을 전달하기 위해 사용자 지정 연계 매개 변수를 정의하거나 일반 구성 요소 매개 변수에 직접 할당할 수 있습니다.

쿼리 문자열에서 제공되는 구성 요소 매개 변수는 다음 형식을 지원합니다.

  • bool,DateTime, decimal, double, float, Guidint, longstring.
  • 이전 타입의 null 가능 변형
  • null 허용 여부에 상관없이 이전 형식들의 배열들

주어진 형식(CultureInfo.InvariantCulture)에 대해 올바른 문화 불변 형식이 적용됩니다.

구성 요소 매개 변수 이름과 다른 쿼리 매개 변수 이름을 사용하려면 [SupplyParameterFromQuery] 특성의 Name 속성을 지정합니다. 다음 예제에서 구성 요소 매개 변수의 C# 이름은 {COMPONENT PARAMETER NAME}입니다. {QUERY PARAMETER NAME} 자리 표시자에 다른 쿼리 매개 변수 이름이 지정됩니다.

구성 요소 매개변수 속성([Parameter])와 달리, [SupplyParameterFromQuery] 속성은 private 외에도 public로 표시될 수 있습니다.

[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }

구성 요소 매개 변수 속성([Parameter])처럼, [SupplyParameterFromQuery] 속성은 항상 .NET 6/7의 public 속성입니다. .NET 8 이상에서는 [SupplyParameterFromQuery] 속성이 public 또는 private로 표시될 수 있습니다.

[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }

URL이 /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman인 다음 예제에서는

  • Filter 속성이 scifi stars로 확인됩니다.
  • Page 속성이 3로 확인됩니다.
  • Stars 배열은 star(Name = "star")라는 쿼리 매개 변수에서 채워지고 LeVar BurtonGary Oldman으로 확인됩니다.

비고

다음으로 라우팅 가능한 페이지 구성 요소의 쿼리 문자열 매개 변수는 `` 지시문 없이도 `@page 구성 요소에서도 작동합니다(예를 들어, 다른 구성 요소에서 사용되는 공유 `Search.razor` 구성 요소의 경우).

Search.razor:

@page "/search"

<h1>Search Example</h1>

<p>Filter: @Filter</p>

<p>Page: @Page</p>

@if (Stars is not null)
{
    <p>Stars:</p>

    <ul>
        @foreach (var name in Stars)
        {
            <li>@name</li>
        }
    </ul>
}

@code {
    [SupplyParameterFromQuery]
    private string? Filter { get; set; }

    [SupplyParameterFromQuery]
    private int? Page { get; set; }

    [SupplyParameterFromQuery(Name = "star")]
    private string[]? Stars { get; set; }
}

Search.razor:

@page "/search"

<h1>Search Example</h1>

<p>Filter: @Filter</p>

<p>Page: @Page</p>

@if (Stars is not null)
{
    <p>Stars:</p>

    <ul>
        @foreach (var name in Stars)
        {
            <li>@name</li>
        }
    </ul>
}

@code {
    [Parameter]
    [SupplyParameterFromQuery]
    public string? Filter { get; set; }

    [Parameter]
    [SupplyParameterFromQuery]
    public int? Page { get; set; }

    [Parameter]
    [SupplyParameterFromQuery(Name = "star")]
    public string[]? Stars { get; set; }
}

GetUriWithQueryParameter를 사용하여 현재 URL에서 하나 이상의 쿼리 매개 변수를 추가, 변경 또는 제거합니다.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})

앞의 예제에서

  • {NAME} 자리 표시자는 쿼리 매개 변수 이름을 지정합니다. {VALUE} 자리 표시자는 이 값을 지원되는 형식으로 지정합니다. 지원되는 형식은 이 섹션의 뒷부분에 나옵니다.
  • 문자열은 단일 매개 변수를 사용하여 현재 URL과 동일하게 반환됩니다.
    • 현재 URL에 쿼리 매개 변수 이름이 없는 경우에 추가됩니다.
    • 현재 URL에 쿼리 매개 변수가 있는 경우에는 제공된 값으로 업데이트됩니다.
    • 제공된 값의 형식이 null을 허용하고 그 값이 null이면 제거됩니다.
  • 주어진 형식(CultureInfo.InvariantCulture)에 대해 올바른 문화 불변 형식이 적용됩니다.
  • 쿼리 매개 변수 이름과 값은 URL로 인코딩됩니다.
  • 형식의 인스턴스가 여러 개인 경우에는 이름이 일치하는 쿼리 매개 변수가 있는 모든 값이 대체됩니다.

GetUriWithQueryParameters를 호출하여 여러 매개 변수가 추가, 업데이트 또는 제거된 Uri에서 생성된 URI를 만듭니다. 프레임워크는 각 값에 대해 value?.GetType()을 사용하여 각 쿼리 매개 변수의 런타임 형식을 확인하고 올바른 문화권 고정 형식을 선택합니다. 이 프레임워크는 지원되지 않는 유형에 대해 오류를 발생시킵니다.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameters({PARAMETERS})

{PARAMETERS} 자리 표시자는 IReadOnlyDictionary<string, object>입니다.

여러 매개 변수를 추가, 업데이트 또는 제거하여 제공된 URI에서 새 URI를 생성하려면 URI 문자열을 GetUriWithQueryParameters에 전달합니다. 프레임워크는 각 값에 대해 value?.GetType()을 사용하여 각 쿼리 매개 변수의 런타임 형식을 확인하고 올바른 문화권 고정 형식을 선택합니다. 이 프레임워크는 지원되지 않는 유형에 대해 오류를 발생시킵니다. 지원되는 형식은 이 섹션의 뒷부분에 나옵니다.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
  • {URI} 자리 표시자는 쿼리 문자열을 포함하거나 포함하지 않는 URI입니다.
  • {PARAMETERS} 자리 표시자는 IReadOnlyDictionary<string, object>입니다.

지원되는 형식은 경로 제약 조건에 대해 지원되는 형식과 동일합니다.

  • bool
  • DateOnly
  • DateTime
  • decimal
  • double
  • float
  • Guid
  • int
  • long
  • string
  • TimeOnly

지원되는 형식은 다음과 같습니다.

  • 이전 타입의 null 가능 변형
  • null 허용 여부에 상관없이 이전 형식들의 배열들

경고

기본적으로 사용하도록 설정된 압축을 사용하면 신뢰할 수 없는 원본에서 데이터를 렌더링하는 보안(인증/권한이 부여된) 대화형 서버 쪽 구성 요소를 만들지 마세요. 신뢰할 수 없는 원본에는 경로 매개 변수, 쿼리 문자열, interop의 데이터 JS 및 타사 사용자가 제어할 수 있는 기타 데이터 원본(데이터베이스, 외부 서비스)이 포함됩니다. 자세한 내용은 ASP.NET Core BlazorSignalR 지침ASP.NET Core Blazor 대화형 서버 쪽 렌더링을 위한 위협 완화 지침을 참조하세요.

매개 변수가 존재하는 경우에 쿼리 매개 변수 값 바꾸기

Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
현재 URL 생성된 URL
scheme://host/?full%20name=David%20Krumholtz&age=42 scheme://host/?full%20name=Morena%20Baccarin&age=42
scheme://host/?fUlL%20nAmE=David%20Krumholtz&AgE=42 scheme://host/?full%20name=Morena%20Baccarin&AgE=42
scheme://host/?full%20name=Jewel%20Staite&age=42&full%20name=Summer%20Glau scheme://host/?full%20name=Morena%20Baccarin&age=42&full%20name=Morena%20Baccarin
scheme://host/?full%20name=&age=42 scheme://host/?full%20name=Morena%20Baccarin&age=42
scheme://host/?full%20name= scheme://host/?full%20name=Morena%20Baccarin

매개 변수가 존재하지 않는 경우에 쿼리 매개 변수 및 값 추가

Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
현재 URL 생성된 URL
scheme://host/?age=42 scheme://host/?age=42&name=Morena%20Baccarin
scheme://host/ scheme://host/?name=Morena%20Baccarin
scheme://host/? scheme://host/?name=Morena%20Baccarin

매개 변수 값이 null인 경우에 쿼리 매개 변수 값 제거

Navigation.GetUriWithQueryParameter("full name", (string)null)
현재 URL 생성된 URL
scheme://host/?full%20name=David%20Krumholtz&age=42 scheme://host/?age=42
scheme://host/?full%20name=Sally%20Smith&age=42&full%20name=Summer%20Glau scheme://host/?age=42
scheme://host/?full%20name=Sally%20Smith&age=42&FuLl%20NaMe=Summer%20Glau scheme://host/?age=42
scheme://host/?full%20name=&age=42 scheme://host/?age=42
scheme://host/?full%20name= scheme://host/

쿼리 매개 변수 추가, 업데이트 및 제거

다음 예제에서

  • name이 제거됩니다(있는 경우).
  • 없는 경우 age25(int) 값으로 추가됩니다. 있는 경우 age25의 값으로 업데이트됩니다.
  • eye color가 추가되거나 green의 값으로 업데이트됩니다.
Navigation.GetUriWithQueryParameters(
    new Dictionary<string, object?>
    {
        ["name"] = null,
        ["age"] = (int?)25,
        ["eye color"] = "green"
    })
현재 URL 생성된 URL
scheme://host/?name=David%20Krumholtz&age=42 scheme://host/?age=25&eye%20color=green
scheme://host/?NaMe=David%20Krumholtz&AgE=42 scheme://host/?age=25&eye%20color=green
scheme://host/?name=David%20Krumholtz&age=42&keepme=true scheme://host/?age=25&keepme=true&eye%20color=green
scheme://host/?age=42&eye%20color=87 scheme://host/?age=25&eye%20color=green
scheme://host/? scheme://host/?age=25&eye%20color=green
scheme://host/ scheme://host/?age=25&eye%20color=green

열거 가능한 값 지원

다음 예제에서

  • full name이 추가되거나 단일 값인 Morena Baccarin으로 업데이트됩니다.
  • ping 매개 변수가 추가되거나 35, 16, 87240으로 대체됩니다.
Navigation.GetUriWithQueryParameters(
    new Dictionary<string, object?>
    {
        ["full name"] = "Morena Baccarin",
        ["ping"] = new int?[] { 35, 16, null, 87, 240 }
    })
현재 URL 생성된 URL
scheme://host/?full%20name=David%20Krumholtz&ping=8&ping=300 scheme://host/?full%20name=Morena%20Baccarin&ping=35&ping=16&ping=87&ping=240
scheme://host/?ping=8&full%20name=David%20Krumholtz&ping=300 scheme://host/?ping=35&full%20name=Morena%20Baccarin&ping=16&ping=87&ping=240
scheme://host/?ping=8&ping=300&ping=50&ping=68&ping=42 scheme://host/?ping=35&ping=16&ping=87&ping=240&full%20name=Morena%20Baccarin

추가 또는 수정된 쿼리 문자열로 탐색하려면 생성된 URL을 NavigateTo에 전달합니다.

다음 예제에서는 호출합니다

  • GetUriWithQueryParameter를 호출하여 name 값을 사용해 Morena Baccarin 쿼리 매개 변수를 추가하거나 바꿉니다.
  • NavigateTo를 호출하여 새 URL에 대한 탐색을 트리거합니다.
Navigation.NavigateTo(
    Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));

요청의 쿼리 문자열은 NavigationManager.Uri 속성에서 가져옵니다.

@inject NavigationManager Navigation

...

var query = new Uri(Navigation.Uri).Query;

쿼리 문자열의 매개 변수를 구문 분석하는 한 가지 방법은 URLSearchParamsJavaScript (JS) interop을 사용하는 것입니다.

export createQueryString = (string queryString) => new URLSearchParams(queryString);

JavaScript 모듈을 사용한 JavaScript 격리에 대한 자세한 내용은 ASP.NET Core Blazor의 .NET 메서드에서 JavaScript 함수 호출을 참조하세요.

요소에 대한 해시된(#) 참조와 함께 다음 방법을 사용하여 명명된 요소로 이동합니다. 구성 요소 내부의 요소 경로와 외부 구성 요소의 요소 경로는 모두 루트 상대 경로를 사용합니다. 선행 슬래시(/)는 선택 사항입니다.

각각의 다음 접근 방식에 대한 예제는 id 구성 요소의 targetElementCounter에 있는 요소로 탐색하는 방법을 보여줍니다.

  • <a> 앵커 요소(href)

    <a href="/counter#targetElement">
    
  • NavLink 구성 요소에는 href이(가) 있습니다.

    <NavLink href="/counter#targetElement">
    
  • NavigationManager.NavigateTo 상대 URL 전달하기:

    Navigation.NavigateTo("/counter#targetElement");
    

다음 예제에서는 구성 요소 내의 명명된 H2 제목 및 외부 구성 요소로 이동하는 방법을 보여 줍니다.

Home (Home.razor) 및 Counter (Counter.razor) 구성 요소에서 다음 태그를 기존 구성 요소 태그의 맨 아래에 배치하여 탐색 대상으로 사용합니다. 브라우저 <div> 스크롤 동작을 보여 주는 인공 세로 공간을 만듭니다.

<div class="border border-info rounded bg-info" style="height:500px"></div>

<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>

앱에 다음 FragmentRouting 구성 요소를 추가합니다.

FragmentRouting.razor:

@page "/fragment-routing"
@inject NavigationManager Navigation

<PageTitle>Fragment routing</PageTitle>

<h1>Fragment routing to named elements</h1>

<ul>
    <li>
        <a href="/fragment-routing#targetElement">
            Anchor in this component
        </a>
    </li>
    <li>
        <a href="/#targetElement">
            Anchor to the <code>Home</code> component
        </a>
    </li>
    <li>
        <a href="/counter#targetElement">
            Anchor to the <code>Counter</code> component
        </a>
    </li>
    <li>
        <NavLink href="/fragment-routing#targetElement">
            Use a `NavLink` component in this component
        </NavLink>
    </li>
    <li>
        <button @onclick="NavigateToElement">
            Navigate with <code>NavigationManager</code> to the 
            <code>Counter</code> component
        </button>
    </li>
</ul>

<div class="border border-info rounded bg-info" style="height:500px"></div>

<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>

@code {
    private void NavigateToElement()
    {
        Navigation.NavigateTo("/counter#targetElement");
    }
}

위치 변경 처리/방지

RegisterLocationChangingHandler에서는 들어오는 탐색 이벤트를 처리하기 위해 처리기를 등록합니다. LocationChangingContext에서 제공하는 처리기의 컨텍스트에는 다음 속성이 포함됩니다.

구성 요소는 OnAfterRender{Async} 수명 주기 메서드에서 여러 위치 변경 핸들러를 등록할 수 있습니다. 탐색은 전체 앱(여러 구성 요소에서)에 등록된 모든 위치 변경 처리기를 호출하며, 내부 탐색은 모두 병렬로 실행합니다. NavigateTo 처리기 외에도 다음과 같이 호출됩니다.

  • 앱의 기본 경로 아래의 URL을 가리키는 링크인 내부 링크를 선택하는 경우
  • 브라우저에서 앞으로 및 뒤로 단추를 사용하여 탐색하는 경우

처리기는 앱의 내부 탐색에 대해서만 실행됩니다. 사용자가 다른 사이트로 이동하는 링크를 선택하거나 주소 표시줄을 다른 사이트로 수동으로 변경하는 경우에는 위치 변경 처리기가 실행되지 않습니다.

IDisposable을 구현하고 등록된 처리기를 삭제하여 등록을 취소합니다. 자세한 내용은 ASP.NET Core Razor 구성 요소 삭제참조하세요.

중요합니다

위치 변경을 처리할 때 JavaScript(JS) interop을 통해 DOM 정리 작업을 실행하지 마세요. 클라이언트에서 MutationObserver 패턴을 JS에 사용합니다. 자세한 내용은 ASP.NET Core Blazor JavaScript 상호 운용성(JS)을 참조하세요.

다음 예제에서는 위치 변경 처리기가 탐색 이벤트에 등록됩니다.

NavHandler.razor:

@page "/nav-handler"
@implements IDisposable
@inject NavigationManager Navigation

<p>
    <button @onclick="@(() => Navigation.NavigateTo("/"))">
        Home (Allowed)
    </button>
    <button @onclick="@(() => Navigation.NavigateTo("/counter"))">
        Counter (Prevented)
    </button>
</p>

@code {
    private IDisposable? registration;

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            registration = 
                Navigation.RegisterLocationChangingHandler(OnLocationChanging);
        }
    }

    private ValueTask OnLocationChanging(LocationChangingContext context)
    {
        if (context.TargetLocation == "/counter")
        {
            context.PreventNavigation();
        }

        return ValueTask.CompletedTask;
    }

    public void Dispose() => registration?.Dispose();
}

내부 탐색은 비동기적으로 취소할 수 있으므로 등록된 처리기에 대한 여러 겹치는 호출이 발생할 수 있습니다. 예를 들어 탐색이 실행되기 전에 사용자가 페이지에서 뒤로 단추를 빠르게 선택하거나 여러 링크를 선택할 때 여러 처리기 호출이 발생할 수 있습니다. 다음은 비동기 탐색 논리의 요약입니다.

  • 위치 변경 처리기가 등록되어 있으면 모든 탐색이 원래대로 되돌려진 다음, 탐색이 취소되지 않은 경우 재생됩니다.
  • 겹치는 탐색 요청이 수행되면 최신 요청은 항상 이전 요청을 취소합니다. 즉, 다음을 의미합니다.
    • 앱은 여러 개의 뒤로 및 앞으로 단추 선택을 단일 선택 영역으로 처리할 수 있습니다.
    • 탐색이 완료되기 전에 사용자가 여러 링크를 선택하면 선택한 마지막 링크에 따라 탐색이 결정됩니다.

탐색 기록 스택의 항목 및 상태를 제어하기 위해 NavigationOptionsNavigateTo로 전달하는 방법에 대한 자세한 내용은 탐색 옵션 섹션을 참조하세요.

추가 예제 코드에 대한 자세한 내용은 NavigationManagerComponentBasicTestApp를 참조하세요(dotnet/aspnetcore 참조 소스).

비고

문서 링크는 .NET 참조 소스를 가리키며, 일반적으로 저장소의 기본 브랜치를 로드합니다. 이는 .NET의 다음 릴리스를 위한 현재 개발 상태를 나타냅니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags 드롭다운 목록을 사용하세요. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.

NavigationLock 구성 요소는 렌더링되는 한 탐색 이벤트를 가로채서 진행하거나 취소하기로 결정할 때까지 지정된 탐색을 효과적으로 "잠금"합니다. 탐색 차단 범위를 구성 요소의 수명으로 지정할 수 있는 경우 NavigationLock를 사용합니다.

NavigationLock 매개 변수:

  • ConfirmExternalNavigation은 사용자에게 외부 탐색을 확인하거나 취소하라는 메시지를 표시하는 브라우저 대화 상자를 설정합니다. 기본값은 false입니다. 확인 대화 상자를 표시하려면 브라우저의 주소 표시줄에 있는 URL을 사용하여 외부 탐색을 트리거하기 전에 페이지와 초기 사용자의 상호 작용이 필요합니다. 상호 작용 요구 사항에 대한 자세한 내용은 Window: beforeunload 이벤트를 참조하세요.
  • OnBeforeInternalNavigation은 내부 탐색 이벤트의 콜백을 설정합니다.

다음은 NavLock 구성 요소에 대한 설명입니다.

  • 사용자가 Microsoft 웹 사이트 링크로 이동하려면 https://www.microsoft.com 탐색이 성공하기 전에 확인을 받아야 합니다.
  • 은 사용자가 대화 상자로 JavaScript () 상호 운용 호출을 통해 탐색을 확인하지 않으면 탐색이 발생하지 않도록 호출됩니다.

NavLock.razor:

@page "/nav-lock"
@inject IJSRuntime JSRuntime
@inject NavigationManager Navigation

<NavigationLock ConfirmExternalNavigation="true" 
    OnBeforeInternalNavigation="OnBeforeInternalNavigation" />

<p>
    <button @onclick="Navigate">Navigate</button>
</p>

<p>
    <a href="https://www.microsoft.com">Microsoft homepage</a>
</p>

@code {
    private void Navigate()
    {
        Navigation.NavigateTo("/");
    }

    private async Task OnBeforeInternalNavigation(LocationChangingContext context)
    {
        var isConfirmed = await JSRuntime.InvokeAsync<bool>("confirm", 
            "Are you sure you want to navigate to the root page?");

        if (!isConfirmed)
        {
            context.PreventNavigation();
        }
    }
}

추가 예제 코드에 대한 자세한 내용은 ConfigurableNavigationLockBasicTestApp 구성 요소를 참조하세요(dotnet/aspnetcore 참조 소스).

NavLink 구성 요소 항목은 리플렉션을 통해 앱의 구성 요소에서 동적으로 만들 수 있습니다. 다음 예제에서는 추가 사용자 지정에 대한 일반적인 방법을 보여 줍니다.

다음 데모에서는 앱의 구성 요소에 일관된 표준 명명 규칙이 사용됩니다.

  • 라우팅 가능한 구성 요소 파일 이름은 파스칼 표기법을 사용합니다. 예를 들어, Pages/ProductDetail.razor입니다.
  • 라우팅 가능한 구성 요소 파일 경로는 kebab 케이스의 URL과 일치하며 구성 요소의 경로 템플릿에 있는 단어 사이에 하이픈이 표시됩니다. 예를 들어 ProductDetail(/product-detail)이라는 경로 템플릿을 사용하는 @page "/product-detail" 구성 요소는 브라우저의 상대 URL /product-detail에서 요청됩니다.

†파스칼 표기법(대문자 카멜 표기법)은 공백과 문장 부호 없이 각 단어의 첫 글자를 대문자로 쓰며, 첫 번째 단어도 포함하는 명명 규칙입니다.
케밥 케이스는 공백과 문장 부호를 사용하지 않고, 모든 글자를 소문자로 하며 단어 사이에 대시를 사용하는 명명 규칙입니다.

기본 Razor 페이지의 NavMenu 마크업에서 NavMenu.razor 구성 요소 (Home) 아래에 컬렉션에서 NavLink 구성 요소가 추가됩니다.

<div class="nav-scrollable" 
    onclick="document.querySelector('.navbar-toggler').click()">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="bi bi-house-door-fill-nav-menu" 
                    aria-hidden="true"></span> Home
            </NavLink>
        </div>

+       @foreach (var name in GetRoutableComponents())
+       {
+           <div class="nav-item px-3">
+               <NavLink class="nav-link" 
+                       href="@Regex.Replace(name, @"(\B[A-Z]|\d+)", "-$1").ToLower()">
+                   @Regex.Replace(name, @"(\B[A-Z]|\d+)", " $1")
+               </NavLink>
+           </div>
+       }

    </nav>
</div>

GetRoutableComponents 블록의 @code 메서드:

public IEnumerable<string> GetRoutableComponents() => 
    Assembly.GetExecutingAssembly()
        .ExportedTypes
        .Where(t => t.IsSubclassOf(typeof(ComponentBase)))
        .Where(c => c.GetCustomAttributes(inherit: true)
                     .OfType<RouteAttribute>()
                     .Any())
        .Where(c => c.Name != "Home" && c.Name != "Error")
        .OrderBy(o => o.Name)
        .Select(c => c.Name);

앞의 예제에서는 렌더링된 구성 요소 목록에 다음 페이지를 포함하지 않습니다.

  • Home 페이지: 페이지가 목록의 맨 위에 표시되고 매개 변수를 설정 Match 해야 하므로 자동으로 생성된 링크와 별도로 나열됩니다.
  • Error 페이지: 오류 페이지는 프레임워크에서만 탐색되며 나열하면 안 됩니다.

샘플 앱에서 이전 코드의 데모를 보려면 Blazor Web App 샘플 앱 또는 Blazor WebAssembly 샘플 앱을 가져오세요.