다음을 통해 공유


6부. ASP.NET Core Razor Pages에 검색 추가

참고 항목

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

Warning

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

Important

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

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

작성자: Rick Anderson

다음 섹션에서는 장르 또는 이름으로 영화 검색이 추가됩니다.

다음 강조 표시된 코드를 Pages/Movies/Index.cshtml.cs에 추가합니다.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

    public IList<Movie> Movie { get;set; }  = default!;

    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }

    public SelectList? Genres { get; set; }

    [BindProperty(SupportsGet = true)]
    public string? MovieGenre { get; set; }

위의 코드에서:

  • SearchString: 사용자가 검색 텍스트 상자에 입력하는 텍스트를 포함합니다. SearchString에는 [BindProperty] 특성이 있습니다. [BindProperty]는 양식 값 및 쿼리 문자열을 속성과 동일한 이름으로 바인딩합니다. [BindProperty(SupportsGet = true)]는 HTTP GET 요청을 바인딩하는 데 필요합니다.
  • Genres: 장르 목록을 포함합니다. Genres를 통해 사용자는 목록에서 장르를 선택할 수 있습니다. SelectListusing Microsoft.AspNetCore.Mvc.Rendering;이 필요합니다.
  • MovieGenre: 사용자가 선택하는 특정 장르를 포함합니다. 예: "서부 영화"
  • GenresMovieGenre는 이 자습서의 뒷부분에서 사용됩니다.

Warning

보안상의 이유로 페이지 모델 속성에 GET 요청 데이터를 바인딩하기 위해 옵트인해야 합니다. 속성에 매핑하기 전에 사용자 입력을 확인합니다. 쿼리 문자열이나 경로 값을 사용하는 시나리오를 지정할 때 GET 바인딩을 옵트인하면 유용합니다.

GET 요청에 속성을 바인딩하려면 [BindProperty] 특성의 SupportsGet 속성을 true로 설정합니다.

[BindProperty(SupportsGet = true)]

자세한 내용은 ASP.NET Core Community 스탠드업을 참조하세요. 토론 가져오기(YouTube)에서 바인딩합니다.

Movies/Index 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 메서드의 첫 번째 줄은 동영상을 선택하는 LINQ 쿼리를 만듭니다.

var movies = from m in _context.Movie
             select m;

이 시점에 쿼리는 정의되기만 했으며 데이터베이스에 대해 실행되지는 않았습니다.

SearchString 속성이 null이 아니거나 비어 있는 경우 동영상 쿼리는 검색 문자열에 대해 필터링하도록 수정됩니다.

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 코드는 람다 식입니다. 람다는 메서드 기반 LINQ 쿼리에서 Where 메서드 또는 Contains와 같은 표준 쿼리 연산자 메서드의 인수로 사용됩니다. LINQ 쿼리는 정의될 때 또는 Where, Contains 또는 OrderBy와 같은 메서드를 호출하여 수정될 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 실현된 값이 반복되거나 ToListAsync 메서드가 호출될 때까지 식의 계산이 지연됩니다. 자세한 내용은 쿼리 실행을 참조하세요.

참고 항목

Contains 메서드는 C# 코드가 아닌 데이터베이스에서 실행됩니다. 쿼리에 대한 대/소문자 구분은 데이터베이스 및 데이터 정렬에 따라 달라집니다. SQL Server에서 Contains는 대/소문자를 구분하는 SQL LIKE로 매핑됩니다. 기본 데이터 정렬을 사용하는 SQLite는 쿼리에 따라 대/소문자를 구분하거나 구분하지 않습니다. 대/소문자를 구분하지 않는 SQLite 쿼리를 만드는 방법에 대한 자세한 내용은 다음을 참조하세요.

Movies 페이지로 이동하고 ?searchString=Ghost와 같은 쿼리 문자열을 URL에 추가합니다. 예들 들어 https://localhost:5001/Movies?searchString=Ghost입니다. 필터링된 동영상이 표시됩니다.

인덱스 보기

다음 경로 템플릿이 인덱스 페이지에 추가되는 경우 검색 문자열이 URL 세그먼트로 전달될 수 있습니다. 예들 들어 https://localhost:5001/Movies/Ghost입니다.

@page "{searchString?}"

이전 경로 제약 조건을 통해 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 제목을 검색할 수 있습니다. "{searchString?}"에서 ?는 선택적 경로 매개 변수임을 의미합니다.

Url에 추가된 단어 ghost와 두 개의 동영상, Ghostbusters 및 Ghostbusters 2의 반환된 동영상 목록이 있는 인덱스 보기

ASP.NET Core 런타임은 모델 바인딩을 사용하여 쿼리 문자열(?searchString=Ghost) 또는 경로 데이터(https://localhost:5001/Movies/Ghost)에서 SearchString 속성의 값을 설정합니다. 모델 바인딩은 대/소문자를 구분하지 않습니다.

그러나 사용자는 영화 검색을 위해 URL을 수정할 수 없습니다. 이 단계에서 동영상을 필터링하도록 UI가 추가됩니다. 경로 제약 조건 "{searchString?}"을 추가한 경우 이를 제거합니다.

Pages/Movies/Index.cshtml 파일을 열고 다음 코드에서 강조 표시된 태그를 추가합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    <thead>

HTML <form> 태그는 다음과 같은 태그 도우미를 사용합니다.

변경 내용을 저장하고 필터를 테스트합니다.

Title 필터 텍스트 상자에 ghost라는 단어를 입력한 Index 보기

장르별 검색

Movies/Index.cshtml.cs 다음 코드로 페이지 OnGetAsync 메서드를 업데이트합니다.

public async Task OnGetAsync()
{
    // <snippet_search_linqQuery>
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;
    // </snippet_search_linqQuery>

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }

    // <snippet_search_selectList>
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    // </snippet_search_selectList>
    Movie = await movies.ToListAsync();
}

다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.

IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

장르는 SelectList 고유한 장르를 프로젝팅하여 생성됩니다.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Razor 페이지에 장르별 검색 추가

Index.cshtml<form> 다음 태그에서 강조 표시된 대로 요소를 업데이트합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

장르로, 영화 제목으로, 그리고 두 가지 모두로 검색하여 앱을 테스트합니다.

장르 선택기 및 제목 텍스트 상자 검색 필터가 포함된 인덱스 보기 완료

다음 단계

다음 섹션에서는 장르 또는 이름으로 영화 검색이 추가됩니다.

다음 강조 표시된 코드를 Pages/Movies/Index.cshtml.cs에 추가합니다.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

    public IList<Movie> Movie { get;set; }  = default!;

    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }

    public SelectList? Genres { get; set; }

    [BindProperty(SupportsGet = true)]
    public string? MovieGenre { get; set; }

위의 코드에서:

  • SearchString: 사용자가 검색 텍스트 상자에 입력하는 텍스트를 포함합니다. SearchString에는 [BindProperty] 특성이 있습니다. [BindProperty]는 양식 값 및 쿼리 문자열을 속성과 동일한 이름으로 바인딩합니다. [BindProperty(SupportsGet = true)]는 HTTP GET 요청을 바인딩하는 데 필요합니다.
  • Genres: 장르 목록을 포함합니다. Genres를 통해 사용자는 목록에서 장르를 선택할 수 있습니다. SelectListusing Microsoft.AspNetCore.Mvc.Rendering;이 필요합니다.
  • MovieGenre: 사용자가 선택하는 특정 장르를 포함합니다. 예: "서부 영화"
  • GenresMovieGenre는 이 자습서의 뒷부분에서 사용됩니다.

Warning

보안상의 이유로 페이지 모델 속성에 GET 요청 데이터를 바인딩하기 위해 옵트인해야 합니다. 속성에 매핑하기 전에 사용자 입력을 확인합니다. 쿼리 문자열이나 경로 값을 사용하는 시나리오를 지정할 때 GET 바인딩을 옵트인하면 유용합니다.

GET 요청에 속성을 바인딩하려면 [BindProperty] 특성의 SupportsGet 속성을 true로 설정합니다.

[BindProperty(SupportsGet = true)]

자세한 내용은 ASP.NET Core Community 스탠드업을 참조하세요. 토론 가져오기(YouTube)에서 바인딩합니다.

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 메서드의 첫 번째 줄은 동영상을 선택하는 LINQ 쿼리를 만듭니다.

// using System.Linq;
var movies = from m in _context.Movie
             select m;

이 시점에 쿼리는 정의되기만 했으며 데이터베이스에 대해 실행되지는 않았습니다.

SearchString 속성이 null이 아니거나 비어 있는 경우 동영상 쿼리는 검색 문자열에 대해 필터링하도록 수정됩니다.

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 코드는 람다 식입니다. 람다는 메서드 기반 LINQ 쿼리에서 Where 메서드 또는 Contains와 같은 표준 쿼리 연산자 메서드의 인수로 사용됩니다. LINQ 쿼리는 정의될 때 또는 Where, Contains 또는 OrderBy와 같은 메서드를 호출하여 수정될 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 실현된 값이 반복되거나 ToListAsync 메서드가 호출될 때까지 식의 계산이 지연됩니다. 자세한 내용은 쿼리 실행을 참조하세요.

참고 항목

Contains 메서드는 C# 코드가 아닌 데이터베이스에서 실행됩니다. 쿼리에 대한 대/소문자 구분은 데이터베이스 및 데이터 정렬에 따라 달라집니다. SQL Server에서 Contains는 대/소문자를 구분하는 SQL LIKE로 매핑됩니다. 기본 데이터 정렬을 사용하는 SQLite는 쿼리에 따라 대/소문자를 구분하거나 구분하지 않습니다. 대/소문자를 구분하지 않는 SQLite 쿼리를 만드는 방법에 대한 자세한 내용은 다음을 참조하세요.

Movies 페이지로 이동하고 ?searchString=Ghost와 같은 쿼리 문자열을 URL에 추가합니다. 예들 들어 https://localhost:5001/Movies?searchString=Ghost입니다. 필터링된 동영상이 표시됩니다.

인덱스 보기

다음 경로 템플릿이 인덱스 페이지에 추가되는 경우 검색 문자열이 URL 세그먼트로 전달될 수 있습니다. 예들 들어 https://localhost:5001/Movies/Ghost입니다.

@page "{searchString?}"

이전 경로 제약 조건을 통해 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 제목을 검색할 수 있습니다. "{searchString?}"에서 ?는 선택적 경로 매개 변수임을 의미합니다.

Url에 추가된 단어 ghost와 두 개의 동영상, Ghostbusters 및 Ghostbusters 2의 반환된 동영상 목록이 있는 인덱스 보기

ASP.NET Core 런타임은 모델 바인딩을 사용하여 쿼리 문자열(?searchString=Ghost) 또는 경로 데이터(https://localhost:5001/Movies/Ghost)에서 SearchString 속성의 값을 설정합니다. 모델 바인딩은 대/소문자를 구분하지 않습니다.

그러나 사용자는 영화 검색을 위해 URL을 수정할 수 없습니다. 이 단계에서 동영상을 필터링하도록 UI가 추가됩니다. 경로 제약 조건 "{searchString?}"을 추가한 경우 이를 제거합니다.

Pages/Movies/Index.cshtml 파일을 열고 다음 코드에서 강조 표시된 태그를 추가합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

HTML <form> 태그는 다음과 같은 태그 도우미를 사용합니다.

변경 내용을 저장하고 필터를 테스트합니다.

Title 필터 텍스트 상자에 ghost라는 단어를 입력한 Index 보기

장르별 검색

Movies/Index.cshtml.cs 다음 코드로 페이지 OnGetAsync 메서드를 업데이트합니다.

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

장르의 SelectList는 고유 장르를 프로젝션함으로써 생성됩니다.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Razor 페이지에 장르별 검색 추가

Index.cshtml<form> 다음 태그에서 강조 표시된 대로 요소를 업데이트합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

장르별, 동영상 제목별 및 둘 다로 검색하여 앱을 테스트합니다.

다음 단계

다음 섹션에서는 장르 또는 이름으로 영화 검색이 추가됩니다.

다음 강조 표시된 코드를 Pages/Movies/Index.cshtml.cs에 추가합니다.

public class IndexModel : PageModel
{
    private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

    public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
    {
        _context = context;
    }

    public IList<Movie> Movie { get;set; }  = default!;

    [BindProperty(SupportsGet = true)]
    public string? SearchString { get; set; }

    public SelectList? Genres { get; set; }

    [BindProperty(SupportsGet = true)]
    public string? MovieGenre { get; set; }

위의 코드에서:

  • SearchString: 사용자가 검색 텍스트 상자에 입력하는 텍스트를 포함합니다. SearchString에는 [BindProperty] 특성이 있습니다. [BindProperty]는 양식 값 및 쿼리 문자열을 속성과 동일한 이름으로 바인딩합니다. [BindProperty(SupportsGet = true)]는 HTTP GET 요청을 바인딩하는 데 필요합니다.
  • Genres: 장르 목록을 포함합니다. Genres를 통해 사용자는 목록에서 장르를 선택할 수 있습니다. SelectListusing Microsoft.AspNetCore.Mvc.Rendering;이 필요합니다.
  • MovieGenre: 사용자가 선택하는 특정 장르를 포함합니다. 예: "서부 영화"
  • GenresMovieGenre는 이 자습서의 뒷부분에서 사용됩니다.

Warning

보안상의 이유로 페이지 모델 속성에 GET 요청 데이터를 바인딩하기 위해 옵트인해야 합니다. 속성에 매핑하기 전에 사용자 입력을 확인합니다. 쿼리 문자열이나 경로 값을 사용하는 시나리오를 지정할 때 GET 바인딩을 옵트인하면 유용합니다.

GET 요청에 속성을 바인딩하려면 [BindProperty] 특성의 SupportsGet 속성을 true로 설정합니다.

[BindProperty(SupportsGet = true)]

자세한 내용은 ASP.NET Core Community 스탠드업을 참조하세요. 토론 가져오기(YouTube)에서 바인딩합니다.

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 메서드의 첫 번째 줄은 동영상을 선택하는 LINQ 쿼리를 만듭니다.

// using System.Linq;
var movies = from m in _context.Movie
             select m;

이 시점에 쿼리는 정의되기만 했으며 데이터베이스에 대해 실행되지는 않았습니다.

SearchString 속성이 null이 아니거나 비어 있는 경우 동영상 쿼리는 검색 문자열에 대해 필터링하도록 수정됩니다.

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 코드는 람다 식입니다. 람다는 메서드 기반 LINQ 쿼리에서 Where 메서드 또는 Contains와 같은 표준 쿼리 연산자 메서드의 인수로 사용됩니다. LINQ 쿼리는 정의될 때 또는 Where, Contains 또는 OrderBy와 같은 메서드를 호출하여 수정될 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 실현된 값이 반복되거나 ToListAsync 메서드가 호출될 때까지 식의 계산이 지연됩니다. 자세한 내용은 쿼리 실행을 참조하세요.

참고 항목

Contains 메서드는 C# 코드가 아닌 데이터베이스에서 실행됩니다. 쿼리에 대한 대/소문자 구분은 데이터베이스 및 데이터 정렬에 따라 달라집니다. SQL Server에서 Contains는 대/소문자를 구분하는 SQL LIKE로 매핑됩니다. 기본 데이터 정렬을 사용하는 SQLite는 쿼리에 따라 대/소문자를 구분하거나 구분하지 않습니다. 대/소문자를 구분하지 않는 SQLite 쿼리를 만드는 방법에 대한 자세한 내용은 다음을 참조하세요.

Movies 페이지로 이동하고 ?searchString=Ghost와 같은 쿼리 문자열을 URL에 추가합니다. 예들 들어 https://localhost:5001/Movies?searchString=Ghost입니다. 필터링된 동영상이 표시됩니다.

인덱스 보기

다음 경로 템플릿이 인덱스 페이지에 추가되는 경우 검색 문자열이 URL 세그먼트로 전달될 수 있습니다. 예들 들어 https://localhost:5001/Movies/Ghost입니다.

@page "{searchString?}"

이전 경로 제약 조건을 통해 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 제목을 검색할 수 있습니다. "{searchString?}"에서 ?는 선택적 경로 매개 변수임을 의미합니다.

Url에 추가된 단어 ghost와 두 개의 동영상, Ghostbusters 및 Ghostbusters 2의 반환된 동영상 목록이 있는 인덱스 보기

ASP.NET Core 런타임은 모델 바인딩을 사용하여 쿼리 문자열(?searchString=Ghost) 또는 경로 데이터(https://localhost:5001/Movies/Ghost)에서 SearchString 속성의 값을 설정합니다. 모델 바인딩은 대/소문자를 구분하지 않습니다.

그러나 사용자는 영화 검색을 위해 URL을 수정할 수 없습니다. 이 단계에서 동영상을 필터링하도록 UI가 추가됩니다. 경로 제약 조건 "{searchString?}"을 추가한 경우 이를 제거합니다.

Pages/Movies/Index.cshtml 파일을 열고 다음 코드에서 강조 표시된 태그를 추가합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

HTML <form> 태그는 다음과 같은 태그 도우미를 사용합니다.

변경 내용을 저장하고 필터를 테스트합니다.

Title 필터 텍스트 상자에 ghost라는 단어를 입력한 Index 보기

장르별 검색

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

장르의 SelectList는 고유 장르를 프로젝션함으로써 생성됩니다.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Razor 페이지에 장르별 검색 추가

Index.cshtml<form> 다음 태그에서 강조 표시된 대로 요소를 업데이트합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

장르별, 동영상 제목별 및 둘 다로 검색하여 앱을 테스트합니다.

다음 단계

다음 섹션에서는 장르 또는 이름으로 영화 검색이 추가됩니다.

다음 강조 표시된 코드를 Pages/Movies/Index.cshtml.cs에 추가합니다.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{
    public class IndexModel : PageModel
    {
        private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

        public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
        {
            _context = context;
        }

        public IList<Movie> Movie { get;set; } = default!;
        [BindProperty(SupportsGet = true)]
        public string ? SearchString { get; set; }
        public SelectList ? Genres { get; set; }
        [BindProperty(SupportsGet = true)]
        public string ? MovieGenre { get; set; }

위의 코드에서:

  • SearchString: 사용자가 검색 텍스트 상자에 입력하는 텍스트를 포함합니다. SearchString에는 [BindProperty] 특성이 있습니다. [BindProperty]는 양식 값 및 쿼리 문자열을 속성과 동일한 이름으로 바인딩합니다. [BindProperty(SupportsGet = true)]는 HTTP GET 요청을 바인딩하는 데 필요합니다.
  • Genres: 장르 목록을 포함합니다. Genres를 통해 사용자는 목록에서 장르를 선택할 수 있습니다. SelectListusing Microsoft.AspNetCore.Mvc.Rendering;이 필요합니다.
  • MovieGenre: 사용자가 선택하는 특정 장르를 포함합니다. 예: "서부 영화"
  • GenresMovieGenre는 이 자습서의 뒷부분에서 사용됩니다.

Warning

보안상의 이유로 페이지 모델 속성에 GET 요청 데이터를 바인딩하기 위해 옵트인해야 합니다. 속성에 매핑하기 전에 사용자 입력을 확인합니다. 쿼리 문자열이나 경로 값을 사용하는 시나리오를 지정할 때 GET 바인딩을 옵트인하면 유용합니다.

GET 요청에 속성을 바인딩하려면 [BindProperty] 특성의 SupportsGet 속성을 true로 설정합니다.

[BindProperty(SupportsGet = true)]

자세한 내용은 ASP.NET Core Community 스탠드업을 참조하세요. 토론 가져오기(YouTube)에서 바인딩합니다.

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 메서드의 첫 번째 줄은 동영상을 선택하는 LINQ 쿼리를 만듭니다.

// using System.Linq;
var movies = from m in _context.Movie
             select m;

이 시점에 쿼리는 정의되기만 했으며 데이터베이스에 대해 실행되지는 않았습니다.

SearchString 속성이 Null 또는 비어 있는 경우 영화 쿼리는 검색 문자열에 대해 필터링하도록 수정됩니다.

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 코드는 람다 식입니다. 람다는 메서드 기반 LINQ 쿼리에서 Where 메서드 또는 Contains와 같은 표준 쿼리 연산자 메서드의 인수로 사용됩니다. LINQ 쿼리는 정의될 때 또는 Where, Contains 또는 OrderBy와 같은 메서드를 호출하여 수정될 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 실현된 값이 반복되거나 ToListAsync 메서드가 호출될 때까지 식의 계산이 지연됩니다. 자세한 내용은 쿼리 실행을 참조하세요.

참고 항목

Contains 메서드는 C# 코드가 아닌 데이터베이스에서 실행됩니다. 쿼리에 대한 대/소문자 구분은 데이터베이스 및 데이터 정렬에 따라 달라집니다. SQL Server에서 Contains는 대/소문자를 구분하는 SQL LIKE로 매핑됩니다. 기본 데이터 정렬을 사용하는 SQLite는 쿼리에 따라 대/소문자를 구분하거나 구분하지 않습니다. 대/소문자를 구분하지 않는 SQLite 쿼리를 만드는 방법에 대한 자세한 내용은 다음을 참조하세요.

Movies 페이지로 이동하고 ?searchString=Ghost와 같은 쿼리 문자열을 URL에 추가합니다. 예들 들어 https://localhost:5001/Movies?searchString=Ghost입니다. 필터링된 동영상이 표시됩니다.

인덱스 보기

다음 경로 템플릿이 인덱스 페이지에 추가되는 경우 검색 문자열이 URL 세그먼트로 전달될 수 있습니다. 예들 들어 https://localhost:5001/Movies/Ghost입니다.

@page "{searchString?}"

이전 경로 제약 조건을 통해 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 제목을 검색할 수 있습니다. "{searchString?}"에서 ?는 선택적 경로 매개 변수임을 의미합니다.

Url에 추가된 단어 ghost와 두 개의 동영상, Ghostbusters 및 Ghostbusters 2의 반환된 동영상 목록이 있는 인덱스 보기

ASP.NET Core 런타임은 모델 바인딩을 사용하여 쿼리 문자열(?searchString=Ghost) 또는 경로 데이터(https://localhost:5001/Movies/Ghost)에서 SearchString 속성의 값을 설정합니다. 모델 바인딩은 대/소문자를 구분하지 않습니다.

그러나 사용자는 영화 검색을 위해 URL을 수정할 수 없습니다. 이 단계에서 동영상을 필터링하도록 UI가 추가됩니다. 경로 제약 조건 "{searchString?}"을 추가한 경우 이를 제거합니다.

Pages/Movies/Index.cshtml 파일을 열고 다음 코드에서 강조 표시된 태그를 추가합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

HTML <form> 태그는 다음과 같은 태그 도우미를 사용합니다.

변경 내용을 저장하고 필터를 테스트합니다.

Title 필터 텍스트 상자에 ghost라는 단어를 입력한 Index 보기

장르별 검색

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

장르의 SelectList는 고유 장르를 프로젝션함으로써 생성됩니다.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Razor 페이지에 장르별 검색 추가

Index.cshtml<form> 다음 태그에서 강조 표시된 대로 요소를 업데이트합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        <select asp-for="MovieGenre" asp-items="Model.Genres">
            <option value="">All</option>
        </select>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

장르별, 동영상 제목별 및 둘 다로 검색하여 앱을 테스트합니다.

다음 단계

다음 섹션에서는 장르 또는 이름으로 영화 검색이 추가됩니다.

다음 강조 표시된 using 문과 속성을 Pages/Movies/Index.cshtml.cs에 추가합니다.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesMovie.Pages.Movies
{

    public class IndexModel : PageModel
    {
        private readonly RazorPagesMovie.Data.RazorPagesMovieContext _context;

        public IndexModel(RazorPagesMovie.Data.RazorPagesMovieContext context)
        {
            _context = context;
        }

        public IList<Movie> Movie { get; set; }
        [BindProperty(SupportsGet = true)]
        public string SearchString { get; set; }
        public SelectList Genres { get; set; }
        [BindProperty(SupportsGet = true)]
        public string MovieGenre { get; set; }

위의 코드에서:

  • SearchString: 사용자가 검색 텍스트 상자에 입력하는 텍스트를 포함합니다. SearchString에는 [BindProperty] 특성이 있습니다. [BindProperty]는 양식 값 및 쿼리 문자열을 속성과 동일한 이름으로 바인딩합니다. [BindProperty(SupportsGet = true)]는 HTTP GET 요청을 바인딩하는 데 필요합니다.
  • Genres: 장르 목록을 포함합니다. Genres를 통해 사용자는 목록에서 장르를 선택할 수 있습니다. SelectListusing Microsoft.AspNetCore.Mvc.Rendering;이 필요합니다.
  • MovieGenre: 사용자가 선택하는 특정 장르를 포함합니다. 예: "서부 영화"
  • GenresMovieGenre는 이 자습서의 뒷부분에서 사용됩니다.

Warning

보안상의 이유로 페이지 모델 속성에 GET 요청 데이터를 바인딩하기 위해 옵트인해야 합니다. 속성에 매핑하기 전에 사용자 입력을 확인합니다. 쿼리 문자열이나 경로 값을 사용하는 시나리오를 지정할 때 GET 바인딩을 옵트인하면 유용합니다.

GET 요청에 속성을 바인딩하려면 [BindProperty] 특성의 SupportsGet 속성을 true로 설정합니다.

[BindProperty(SupportsGet = true)]

자세한 내용은 ASP.NET Core Community 스탠드업을 참조하세요. 토론 가져오기(YouTube)에서 바인딩합니다.

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    var movies = from m in _context.Movie
                 select m;
    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    Movie = await movies.ToListAsync();
}

OnGetAsync 메서드의 첫 번째 줄은 동영상을 선택하는 LINQ 쿼리를 만듭니다.

// using System.Linq;
var movies = from m in _context.Movie
             select m;

이 시점에 쿼리는 정의되기만 했으며 데이터베이스에 대해 실행되지는 않았습니다.

SearchString 속성이 Null 또는 비어 있는 경우 영화 쿼리는 검색 문자열에 대해 필터링하도록 수정됩니다.

if (!string.IsNullOrEmpty(SearchString))
{
    movies = movies.Where(s => s.Title.Contains(SearchString));
}

s => s.Title.Contains() 코드는 람다 식입니다. 람다는 메서드 기반 LINQ 쿼리에서 Where 메서드 또는 Contains와 같은 표준 쿼리 연산자 메서드의 인수로 사용됩니다. LINQ 쿼리는 정의될 때 또는 Where, Contains 또는 OrderBy와 같은 메서드를 호출하여 수정될 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 실현된 값이 반복되거나 ToListAsync 메서드가 호출될 때까지 식의 계산이 지연됩니다. 자세한 내용은 쿼리 실행을 참조하세요.

참고 항목

Contains 메서드는 C# 코드가 아닌 데이터베이스에서 실행됩니다. 쿼리에 대한 대/소문자 구분은 데이터베이스 및 데이터 정렬에 따라 달라집니다. SQL Server에서 Contains는 대/소문자를 구분하는 SQL LIKE로 매핑됩니다. 기본 데이터 정렬을 사용하는 SQLite는 쿼리에 따라 대/소문자를 구분하거나 구분하지 않습니다. 대/소문자를 구분하지 않는 SQLite 쿼리를 만드는 방법에 대한 자세한 내용은 다음을 참조하세요.

Movies 페이지로 이동하고 ?searchString=Ghost와 같은 쿼리 문자열을 URL에 추가합니다. 예들 들어 https://localhost:5001/Movies?searchString=Ghost입니다. 필터링된 동영상이 표시됩니다.

인덱스 보기

다음 경로 템플릿이 인덱스 페이지에 추가되는 경우 검색 문자열이 URL 세그먼트로 전달될 수 있습니다. 예들 들어 https://localhost:5001/Movies/Ghost입니다.

@page "{searchString?}"

이전 경로 제약 조건을 통해 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 제목을 검색할 수 있습니다. "{searchString?}"에서 ?는 선택적 경로 매개 변수임을 의미합니다.

Url에 추가된 단어 ghost와 두 개의 동영상, Ghostbusters 및 Ghostbusters 2의 반환된 동영상 목록이 있는 인덱스 보기

ASP.NET Core 런타임은 모델 바인딩을 사용하여 쿼리 문자열(?searchString=Ghost) 또는 경로 데이터(https://localhost:5001/Movies/Ghost)에서 SearchString 속성의 값을 설정합니다. 모델 바인딩은 대/소문자를 구분하지 않습니다.

그러나 사용자는 영화 검색을 위해 URL을 수정할 수 없습니다. 이 단계에서 동영상을 필터링하도록 UI가 추가됩니다. 경로 제약 조건 "{searchString?}"을 추가한 경우 이를 제거합니다.

Pages/Movies/Index.cshtml 파일을 열고 다음 코드에서 강조 표시된 태그를 추가합니다.

@page
@model RazorPagesMovie.Pages.Movies.IndexModel

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>

<form>
    <p>
        Title: <input type="text" asp-for="SearchString" />
        <input type="submit" value="Filter" />
    </p>
</form>

<table class="table">
    @*Markup removed for brevity.*@

HTML <form> 태그는 다음과 같은 태그 도우미를 사용합니다.

변경 내용을 저장하고 필터를 테스트합니다.

Title 필터 텍스트 상자에 ghost라는 단어를 입력한 Index 보기

장르별 검색

인덱스 페이지의 OnGetAsync 메서드를 다음 코드로 업데이트합니다.

public async Task OnGetAsync()
{
    // Use LINQ to get list of genres.
    IQueryable<string> genreQuery = from m in _context.Movie
                                    orderby m.Genre
                                    select m.Genre;

    var movies = from m in _context.Movie
                 select m;

    if (!string.IsNullOrEmpty(SearchString))
    {
        movies = movies.Where(s => s.Title.Contains(SearchString));
    }

    if (!string.IsNullOrEmpty(MovieGenre))
    {
        movies = movies.Where(x => x.Genre == MovieGenre);
    }
    Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    Movie = await movies.ToListAsync();
}

다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.

// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
                                orderby m.Genre
                                select m.Genre;

장르의 SelectList는 고유 장르를 프로젝션함으로써 생성됩니다.

Genres = new SelectList(await genreQuery.Distinct().ToListAsync());

Razor 페이지에 장르별 검색 추가

  1. Index.cshtml<form> 다음 태그에서 강조 표시된 대로 요소를 업데이트합니다.

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
        @*Markup removed for brevity.*@
    
    
  2. 장르별, 동영상 제목별 및 둘 다로 검색하여 앱을 테스트합니다.

다음 단계