کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

آموزش ASP.Net Mvc Core -آموزش افزودن قابلیت Search به برنامه ASP.Net Mvc Core

برای مشاهده سر فصل های مربوط به آموزش MVC Core کلیک نمایید.

آموزش MVC Core - آموزش اضافه کردن Search Box به ASP.Net MVC Core

در این بخش با اضافه کردن قابلیت جستجو به اکشن Index شما می توانید فیلم ها را بر اساس نام و ژانر جستجو کنید.

اکشن Index رو مطابق کدهای زیر تغییر بدهید:

public async Task< IActionResult > Index(string searchString)
{
    var movies = from m in _context.Movie
                 select m;
    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }
    return View(await movies.ToListAsync());
}

اولین خط از متد Index یک query از نوع LINQ برای انتخاب فیلم می باشد.

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

query فقط در این نقطه تعریف شده و در برابر پایگاه داده اجرا نشده است.

اگر searchString پارمتر حاوی یک رشته String باشد ،درخواست فیلم برای فیلتر کردن بر روی مقدار رشته جستجو اصلاح شده(modified ) است:

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

این قسمت از کد (s => s.Title.Contains()) در واقع یک Lambda Expression هست. Lambdas در روشهای مبتنی بر LINQ queriesبه عنوان استدلال هایی برای روش های query استاندارد مانند روش Whereو یا Contains (استفاده شده در کد بالا) استفاده می شود. Lambda Expressionزمانی انجام می شود که آنها تعریف شده یا زمانی که با فراخوانی یک روش مانند Where، Containsیا OrderBy اصلاح می شوند(modified ). در عوض، اجرای پرس و جو(query ) به تعویق می افتد. این بدان معنی است که ارزیابی یک عبارت به تعویق می افتد تا زمانی که ارزش واقعی آن در واقع تکرار شود یا روش ToListAsync فراخوانی شود.

نکته: متد Contains در پایگاه داده اجرا می شود نه در کد c # که در بالا نشان داده شده است.حالت case sensitivity بستگی به پایگاه داده مورد استفاده و نوع مقایسه دارد. در SQL Server ،حاوی نقشه هایی به SQL LIKE است که حساس به محتوا هستند.در SQL LIKE با مقادیر پیش فرض، حساس به حروف است.

به آدرس /Movies/Index بروید .یک query string مانند( ?searchString=Ghost )به URL اضافه کنید. فیلم های فیلتر شده نمایش داده می شوند.

آموزش Asp.net Core

اگر شما ورودی متد Index رو پارامتری به نام ID قرار بدهید ،این پارامتر با پارامتر ID که در فایل Startup.cs. قرار دارد و اختیاری می باشد مطابقت می کند.

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

شما برای اینکه بتوانید با سرعت پارامتر SearchString را به ID تغییر دهید بر روی پارامتر SearchString راست کلید کرده و گزینه Rename را انتخاب کنید.

آموزش Asp.net Core

اهدافی که باید تغییر پیدا کنند در عکس زیر هایلات شده است:

آموزش Asp.net Core

پارامتر id را جایگزین می کنیم:

آموزش Asp.net Core

متد index قبل از تغییر:

public async Task< IActionResult > Index(string searchString)
{
    var movies = from m in _context.Movie
                 select m;
    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }
    return View(await movies.ToListAsync());
}

متد Index به روز شده با پارامتر id :

public async Task< IActionResult > Index(string id)
{
    var movies = from m in _context.Movie
                 select m;
    if (!String.IsNullOrEmpty(id))
    {
        movies = movies.Where(s => s.Title.Contains(id));
    }
    return View(await movies.ToListAsync());
}

شما هم اکنون می توانید عنوان جستجو را به عنوان route data (بخش URL) به جای به عنوان یک مقدار query string منتقل کنید.

آموزش Asp.net Core

با این حال، نمی توانید انتظار داشته باشید که کاربران هر بار که بخواهند یک فیلم را جستجو کنند، URL را تغییر دهند. بنابراین اکنون شما UI را برای کمک به فیلتر کردن فیلم ها اضافه می کنید.اگر ورودی متد Index را به حالت قبل برگردانید چگونه میتوان مانند id جستجو کرد برای یافتن پاسخ دوباره متد index را کامل به حالت پارامتر SearchString بر می گردانیم:

public async Task< IActionResult > Index(string searchString)
{
    var movies = from m in _context.Movie
                 select m;
    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }
    return View(await movies.ToListAsync());
}

از مسیر Views/Movies/Index.cshtml فایل را باز کرده و با استفاده از < form > کد زیر را اضافه می کنیم:

ViewData["Title"] = "Index";
}
< h2 >Index< /h2 >
< p >
    < a asp-action="Create" >Create New< /a >
< /p >
< form asp-controller="Movies" asp-action="Index" >
    < p >
        Title: < input type="text" name="SearchString" >
        < input type="submit" value="Filter" / >
    < /p >
< /form >
< table class="table" >
                            < thead >

تگ < Form > از Form Tag Helper استفاده می کند،بنابراین هنگامی که فرم را ارسال می کنید،رشته فیلتر به اکشن Index از کنترلر Movie ارسال می شود.تغییرات خود را ذخیره کنید و سپس فیلتر را آزمایش کنید.

آموزش Asp.net Core

***** Overload یعنی چند متد هم نام با امضاء های (نوع ورودی ها، و نوع خروجی ها) مختلف در یک کلاس یا یک object هستند اما Override یعنی فرزند متدهای ارث بری شده از پدر را تغییر دهد.

همانطور که انتظار داشتید هیچ [HttpPost] از متد index Overload نشده است.شما به آن نیاز ندارید،زیرا این متد وضعیت برنامه را تغییر نمی دهد، فقط فیلتر کردن داده ها.

شما میتوانید [HttpPost] Index زیر را اضافه کنید:

[HttpPost]
public string Index(string searchString, bool notUsed)
{
    return "From [HttpPost]Index: filter on " + searchString;
}

پارامتر notUsed برای ایجاد یک Overload از متد index استفاده میشود. بعدا در مورد آموزش آن صحبت خواهیم کرد.


اگر این متد را اضافه کنید، فراخوانی عمل با متد index [HttpPost] مطابقت دارد و متد [HttpPost] index اجرا می شود همانطور که در تصویر زیر نشان داده شده است.


آموزش Asp.net Core

با این حال، حتی اگر شما این نسخه [HttpPost] را به متد index اضافه کنید،محدودیت هایی در پیاده سازی آن وجود دارد. تصور کنید که میخواهید یک جستجوی خاص را نشانه گذاری کنید یا میخواهید یک پیوند را به دوستانتان ارسال کنید تا بتوانید لیستی از فیلمهای فیلتر شده را ببینید. توجه داشته باشید که URL درخواست شده از HTTP POST همان آدرس URL درخواست شده از Http Get است (localhost:xxxxx/Movies/Index) هیچ اطلاعات جستجویی در URL وجود ندارد. اطلاعات رشته جستجو به سرور به عنوان یک form field value ارسال می شود. شما می توانید با استفاده از ابزارهای توسعه دهنده مرورگر یا بهتر از آن Fiddler tool را تأیید کنید. تصویر زیر نشانگر ابزارهای برنامه نویسی Chrome را نشان می دهد:


آموزش Asp.net Core

شما می توانید پارامتر جستجو و XSRF token را در بدنه request مشاهده کنید. توجه داشته باشید، همانطور که در آموزش قبلی اشاره شد، Form Tag Helper یک نشانه(token) ضد جعل XSRF را تولید می کند. ما داده ها را اصلاح نمی کنیم، بنابراین ما نیازی به تأیید نشانه(token) در متد کنترل نداریم. از آنجا که پارامتر جستجو در قسمت درخواست و نه URL است، شما نمی توانید این اطلاعات جستجو را به نشانه گذاری(bookmark) و یا به اشتراک گذاری با دیگران به اشتراک بگذارید. ما این را با مشخص کردن درخواست HTTP GET را باید رفع کنیم.

توجه داشته باشید که intelliSense به ما کمک می کند نشانه گذاری را به روز رسانی کنیم.

آموزش Asp.net Core
آموزش Asp.net Core

به فونت متمایز در تگ < form > دقت کنید.این فونت متمایز شده نشان میدهد که تگ توسط Tag Helpers پشتیبانی می شود.


آموزش Asp.net Core

در حال حاضر زمانی که یک جستجو را ارسال می کنید، URL حاوی query string است.جستجو به متد HttpGet Index می رسد و انجام خواهد شد حتی اگر یک متد HttpPost Index داشته باشیم.


آموزش Asp.net Core

کد زیر تغییرات تگ form را نشان می دهد:

< form asp-controller="Movies" asp-action="Index" method="get" >
    

اضافه کردن جستجو بر اساس ژانر در ASP.Net MVC Core

کلاس MovieGenreViewModel به فولدر Models اضافه می کنیم.

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcMovie.Models
{
    public class MovieGenreViewModel
    {
        public List< Movie > movies;
        public SelectList genres;
        public string movieGenre { get; set; }
    }
}

movie-genre view model شامل :


  • یک لیست از فیلم ها
  • یک SelectList که شامل لسیتی از ژانر ها است. این به کاربر اجازه می دهد ژانر را از لیست انتخاب کند.
  • movieGenre که شامل ژانر انتخاب شده است.

در متد index از کنترلر MoviesController.cs کدهای زیر را وارد کنید:


// Requires using Microsoft.AspNetCore.Mvc.Rendering;
public async Task< IActionResult > Index(string movieGenre, string searchString)
{
    // 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);
    }
    var movieGenreVM = new MovieGenreViewModel();
    movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());
    movieGenreVM.movies = await movies.ToListAsync();
    return View(movieGenreVM);
}
                            

کد زیر یک query LINQ است که تمام ژانرها را از پایگاه داده بازیابی می کند.


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

SelectList از ژانرها با طراحی ژانرهای مجزا ایجاد می شود (ما نمی خواهیم لیست انتخاب ما دارای ژانرهای تکراری باشد).


movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync())

فایل Index.cshtml با کدهای زیر به روز کنید:


@model MvcMovie.Models.MovieGenreViewModel
@{
    ViewData["Title"] = "Index";
}
< h2 >Index< /h2 >
< p >
   < a asp-action="Create" >Create New< /a >
< /p >
< form asp-controller="Movies" asp-action="Index" method="get" >
   < p >
            < select asp-for="movieGenre" asp-items="Model.genres" >
            < option value="" >All<    /option >
        < /select >
        Title: < input type="text" name="SearchString" >
        < input type="submit" value="Filter" / >
    < /p >
< /form >
< table class="table" >
    < thead >
        < tr >
            < th >
                @Html.DisplayNameFor(model = > model.movies[0].Title)
            < /th >
            < th >
                @Html.DisplayNameFor(model = > model.movies[0].ReleaseDate)
            < /th >
            < th >
                @Html.DisplayNameFor(model = > model.movies[0].Genre)
            < /th >
            < th >
                @Html.DisplayNameFor(model = > model.movies[0].Price)
            < /th >
            < th >< /th >
        < /tr >
    < /thead >
    < tbody >
        @foreach (var item in Model.movies)
        {
            < tr >
                < td >
                    @Html.DisplayFor(modelItem = > item.Title)
                < /td >
                < td >
                    @Html.DisplayFor(modelItem = > item.ReleaseDate)
                < /td >
                < td >
                    @Html.DisplayFor(modelItem = > item.Genre)
                < /td >
                < td >
                    @Html.DisplayFor(modelItem = > item.Price)
                < /td >
                < td >
                    < a asp-action="Edit" asp-route-id="@item.ID" >Edit< /a > |
                    < a asp-action="Details" asp-route-id="@item.ID" >Details< /a > |
                    < a asp-action="Delete" asp-route-id="@item.ID" >Delete< /a >
                < /td >
            < /tr >
        }
    < /tbody >
< /table >

عبارت lambda مورد استفاده در HTML Helper زیر را بررسی کنید:


@Html.DisplayNameFor(model => model.movies[0].Title)


در کد قبلی، DisplayNameFor HTML Helper مالکیت title را که در عبارت lambda اشاره شده است، برای تعیین نام نمایش بازرسی می کند. از آنجا که لامبدا به جای ارزیابی بازرسی می شود، شما نقض دسترسی را دریافت نمی کنید زمانی که model,model movie,model movie[0] صفر یا خالی هستند.وقتی عبارت lambda ارزیابی شد(برای مثال @Html.DisplayFor(modelItem => item.Title))مدل property values ارزیابی می شوند.


برنامه را با جستجو ژانر و عنوان فیلم و هردو تست کنید.


1396/07/20 8187 1785
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...