您当前的位置: 首页 >  .net

寒冰屋

暂无认证

  • 2浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

通过示例介绍ASP.NET Core MVC(第3部分)

寒冰屋 发布时间:2022-08-14 22:44:38 ,浏览量:2

目录

介绍

使用代码

过滤图书对象

改进URL方案

创建导航视图组件

创建genres导航

指示当前genres

修复分页

兴趣点

介绍

在第1部分中,BooksStore应用程序可以在单个页面上显示数据库中的书籍,在第2部分中,它可以在一个页面上显示较少数量的书籍,并且用户可以从一个页面移动到另一个页面以查看整个目录。在本文中,我们将添加对按类型浏览书籍的支持。

使用代码 过滤图书对象

首先,要按Book类型过滤对象,我们将通过更改Models/ViewModels文件夹中的BooksListViewModel.cs文件来添加一个名为CurrentGenre的视图模型属性:

using System.Collections.Generic;
namespace BooksStore.Models.ViewModels
{
    public class BooksListViewModel
    {
        public IEnumerable Books { get; set; }
        public PagingInfo PagingInfo { get; set; }
        public string CurrentGenre { get; set; }
    }
}

下一步是更新Home控制器,以便Index操作方法按genres过滤Book对象,并使用我们添加到视图模型的属性来指示使用以下代码选择了哪个genres:

public IActionResult Index(string genre, int bookPage = 1)
            => View(new BooksListViewModel
            {
                Books = repository.Books
                   .Where(p => genre == null || p.Genre == genre)
                   .OrderBy(p => p.BookID)
                   .Skip((bookPage - 1) * PageSize)
                   .Take(PageSize),
                PagingInfo = new PagingInfo
                {
                    CurrentPage = bookPage,
                    ItemsPerPage = PageSize,
                    TotalItems = repository.Books.Count()
                },
                CurrentGenre = genre
            });

在前面的代码中:

  • 我们添加了一个名为genre的参数。此参数用于增强LINQ查询:如果类型不是null,则仅选择具有匹配Genre属性的Book对象。
  • 我们还设置了CurrentGenre属性的值。

运行应用程序:

使用以下URL选择自助类型:http://localhost:44333/?genre=Self-Help

但是,这些更改意味着PagingInfo.TotalItems的值计算不正确,因为它没有考虑genres过滤器。而且,很明显,我们和我们的用户不希望使用URL导航到genres。

改进URL方案

我们将通过更改Startup类Configure方法中的路由配置来改进URL方案,以使用以下代码创建一组更有用的URL:

app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute("genpage",
                         "{genre}/{bookPage:int}",
                    new { Controller = "Home", action = "Index" });
                endpoints.MapControllerRoute("page", "{bookPage:int}",
                    new { Controller = "Home", action = "Index", bookPage = 1 });
                endpoints.MapControllerRoute("genre", "{genre}",
                    new { Controller = "Home", action = "Index", bookPage = 1 });
                endpoints.MapControllerRoute("pagination",
                    "Books/{bookPage}",
                    new { Controller = "Home", action = "Index", bookPage = 1 });
                endpoints.MapDefaultControllerRoute();
            });

通过使用ASP.NET Core路由系统来处理传入请求和生成传出URL,我们可以确保应用程序中的所有URL都是一致的。

现在我们需要一种方法来从视图中接收额外的信息,而不必向标签助手类添加额外的属性。幸运的是,标签助手有一个很好的特性,它允许在一个集合中一起接收具有公共前缀的属性。BooksStore /MyTagHelper文件夹中的MyPageLink.cs文件中的前缀值,代码如下:

public class MyPageLink : TagHelper
    {
        private IUrlHelperFactory urlHelperFactory;
        public MyPageLink(IUrlHelperFactory helperFactory)
        {
            urlHelperFactory = helperFactory;
        }

        [ViewContext]
        [HtmlAttributeNotBound]
        public ViewContext ViewContext { get; set; }
        public PagingInfo PageModel { get; set; }
        public string PageAction { get; set; }

        [HtmlAttributeName(DictionaryAttributePrefix = "page-url-")]
        public Dictionary PageUrlValues { get; set; }
                = new Dictionary();

        public bool PageClassesEnabled { get; set; } = false;
        public string PageClass { get; set; }
        public string PageClassNormal { get; set; }
        public string PageClassSelected { get; set; }

        public override void Process(TagHelperContext context,
                TagHelperOutput output)
        {
            IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext);
            TagBuilder result = new TagBuilder("div");
            for (int i = 1; i  x.Genre)
                .Distinct()
                .OrderBy(x => x));
        }    
    }
}

在前面的代码中,构造函数定义了一个IBooksStoreRepository参数。在该Invoke方法中,我们使用LINQ选择和排序存储库中的genres集,并将它们作为参数传递给该View方法,该方法呈现默认的Razor局部视图,其详细信息从使用IViewComponentResult对象的方法返回。

Razor使用不同的约定来定位视图组件选择的视图。视图的默认名称和搜索视图的位置都与用于控制器的不同。为此,我们将在BooksStore项目中创建Views/Shared/Components/GenreNavigation文件夹,并向其中添加一个名为Default.cshtml的Razor视图,我在其中添加了具有以下标记的内容:

@model IEnumerable

    Home

@foreach (string genre in Model)
{
    
        @genre
    
}

运行应用程序以查看genres导航按钮。如果单击按钮,项目列表将更新为仅显示所选genres的项目,如下图所示:

指示当前genres

我们需要向用户提供一些清晰的视觉反馈,以表明选择了哪种类型。为此,第一步,我们将使用该RouteData属性访问请求数据,以获取当前所选genres的值。在下面的代码中,我们将在BooksStore/ViewComponents文件夹中的GenreNavigation.cs文件中传递选定的genres。

public IViewComponentResult Invoke()
  {
      ViewBag.SelectedGenre = RouteData?.Values["genre"];
      return View(repository.Books
            .Select(x => x.Genre)
            .Distinct()
            .OrderBy(x => x));
  }

在Invoke方法内部,我们为ViewBag对象动态分配了一个SelectedGenre属性,并将其值设置为当前genres,该genres是通过该RouteData属性返回的上下文对象获取的。ViewBag是一个动态对象,它允许我们简单地通过为它们分配值来定义新属性。

接下来,我们可以更新视图组件选择的视图,并改变用于样式链接的CSS类,以便代表当前类型的类是不同的。为此,我们将使用以下标记更改Views/Shared/Components/GenreNavigation文件夹中的Default.cshtml文件:

@model IEnumerable

    Home

@foreach (string genre in Model)
{
     
        @genre
    
}

我们在class属性中使用了Razor表达式,将btn-primary类应用于表示所选genres的元素,否则应用到btn-outline-primary类。运行应用程序并请求自助类型:

修复分页

目前,页面链接的数量取决于存储库中的书籍总数,而不是所选类型的书籍数量。这意味着我们可以点击Self-Help类型的第2页的链接,因为没有足够的书来填满两页,所以最终会得到一个空白页,如下图所示:

我们可以通过更新Home控制器中的Index操作方法来解决这个问题,以便分页信息使用以下代码传递genres:

public IActionResult Index(string genre, int bookPage = 1)
            => View(new BooksListViewModel
            {
                Books = repository.Books
                   .Where(p => genre == null || p.Genre == genre)
                   .OrderBy(p => p.BookID)
                   .Skip((bookPage - 1) * PageSize)
                   .Take(PageSize),
                PagingInfo = new PagingInfo
                {
                    CurrentPage = bookPage,
                    ItemsPerPage = PageSize,
                    TotalItems = genre == null ?
                        repository.Books.Count() :
                        repository.Books.Where(e =>
                            e.Genre == genre).Count()
                },
                CurrentGenre = genre
            });

运行应用程序:

兴趣点

我们添加了对分页的支持,以便视图在一个页面上显示较少数量的书籍,并且用户可以从一个页面移动到另一个页面以查看整个目录。我们使用Bootstrap来设计应用程序的外观,我们还添加了对按类型导航书籍的支持。在下一篇文章中,我们将添加一个购物车,它是电子商务应用程序的重要组件。

https://www.codeproject.com/Articles/5327794/An-Introduction-to-ASP-NET-Core-MVC-through-an-E-3

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0742s