none
Не выбираются товары по категориям RRS feed

  • Вопрос

  • Добрый день , начал изучать asp core 2 учусь по учебнику asp.net core mvc с примерами на c# для профессионалов. Там я застрял на пункте где делается навигация , можете подсказать что я не так делаю.
    Конфиг файл

     public class Startup
        {
            public IConfiguration Configuration;
            public Startup(IConfiguration configuration) => Configuration = configuration;
           
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<ApplicationDbContext>(options
                    => options.UseSqlServer(Configuration.GetConnectionString("LibraryConnection")));
                services.AddTransient<IProductRepository, EFProductRepository>();
                services.AddMvc();
            }
     
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                app.UseDeveloperExceptionPage();
                app.UseStaticFiles();
                app.UseStatusCodePages();
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                    name: null,
                    template: "{category}/Page{productPage:int}",
                    defaults: new { Controller = "Product", action = "List" });
     
                    routes.MapRoute(
                    name: null,
                    template: "Page{productPage:int}",
                    defaults: new { controller = "Product", action = "List", productPage = 1 });
     
                    routes.MapRoute(
                        name: null,
                        template: "{category}",
                        defaults: new { controller = "Product", action = "List", productPage = 1 });
     
                    routes.MapRoute(
                        name: null,
                        template: "",
                        defaults: new { controller = "Product", action = "List", productPage = 1 });
     
                    routes.MapRoute(name: null, template: "{controller}/{action}/{id?}");
     
                });
                SeedData.EnsurePopulated(app);
            }
        }

    Контроллер

    namespace SportStore2.Controllers
    {
        public class ProductController:Controller
        {
            private IProductRepository repository;
            public int PageSize = 4;
            public ProductController(IProductRepository repo)
            {
                repository = repo;
            }
     
            public ViewResult List(string category, int page = 2) =>
                View(new ProductsListViewModel
                {
                    Products = repository.Products
                    .Where(p=>category==null||p.category==category)
                    .OrderBy(p => p.ProductID)
                    .Skip((page - 1) * PageSize)
                    .Take(PageSize),
                    PagingInfo = new PagingInfo
                    {
                        CurrentPage = page,
                        ItemsPerPage = PageSize,
                        TotalItems = repository.Products.Count()
                    },
                    CurrentCategory = category
                })
                ;
        }
    }

    Далее получается этот контроллер передает данные из базы в представление

    <!DOCTYPE html>
     
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
              
        <title>SportStore</title>
    </head>
    <body>
        <div class="navbar navbar-inverse bg-inverse" role="navigation">
            <a class="navbar-brand" href="#">SPORT STORE</a>
        </div>
        <div class="row m-1 p-1">
            <div id="categories" class="col-3">
                @await Component.InvokeAsync("NavigationMenu")
            </div>
            <div class="col-9">
                @RenderBody()
            </div>
        </div>
    </body>
    </html>

    Тут есть компонент навигатион меню , тоесть в него создали свой контроллер вот он

        public class NavigationMenuViewComponent:ViewComponent
        {
            private IProductRepository repository;
            public NavigationMenuViewComponent(IProductRepository repo)
            {
                repository = repo;
            }
     
            public IViewComponentResult Invoke()
            {
                ViewBag.SelectedCategory = RouteData?.Values["category"];
                return View(repository.Products
                    .Select(x => x.category)
                    .Distinct()
                    .OrderBy(x => x));
            }
        }

    Далее есть само представление для рендер боди , оно находится в List вот он

    @model SportStore2.Models.ViewModels.ProductsListViewModel
     
    @foreach(var p in Model.Products)
    {
        @Html.Partial("ProductSummary", p);
    }
    <div page-model="@Model.PagingInfo" page-action="List" page-classes-enabled="true"
    page-class="btn" page-class-normal="btn_secondary" 
    page-class-selected="btn_primary" page-url-category="@Model.CurrentCategory"
     class="btn-group pull-right m-1"></div>


    Дальше у нас там реализован компонент ProductSummary вот он


    @model Product
    <div class="card card-outline-primary m-1 p-1">
        <div class="bg-faded p-1">
            <h4>
                @Model.Name
                <span class="badge badge-pill badge-primary" style="float:right">
                    <small>@Model.Price.ToString("c")</small>
                </span>
            </h4>
        </div>
        <div class="card-text p-1">@Model.Decription</div>
    </div>

    Так же сделан Тегхелпер который генерирует элементы и ссылки а также берет данные из тех кнопок по которы кликнет юзер.


    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Rendering;
    using Microsoft.AspNetCore.Mvc.Routing;
    using Microsoft.AspNetCore.Mvc.ViewFeatures;
    using Microsoft.AspNetCore.Razor.TagHelpers;
    using SportStore2.Models.ViewModels;
    using System.Collections.Generic;
    namespace SportStore2.Infrastructure
    {
        [HtmlTargetElement("div", Attributes = "page-model")]
            public class PageLinkTagHelper : TagHelper
            {
                private IUrlHelperFactory urlHelperFactory;
                public PageLinkTagHelper(IUrlHelperFactory helperFactory)
                {
                    urlHelperFactory = helperFactory;
                }
            
                [ViewContext]
                [HtmlAttributeNotBound]
                public ViewContext ViewContext { set; get; }
                public PagingInfo PageModel { set; get; }
                public string PageAction { set; get; }
            [HtmlAttributeName(DictionaryAttributePrefix = "page-url-")]
            public Dictionary<string, object> PageUrlValues { set; get; }
            = new Dictionary<string, object>();
     
                public bool PageClassesEnabled { set; get; } = false;
                public string PageClass { set; get; }
                public string PageClassNormal { set; get; }
                public string PageClassSelected { set; get; }
                public override void Process(TagHelperContext context, TagHelperOutput output)
                {
                    IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext);
                    TagBuilder result = new TagBuilder("div");
                    for(int i=1;i<= PageModel.TotalPages;i++)
                    {
                    TagBuilder tag = new TagBuilder("a");
                        PageUrlValues["productPage"] = i;
                        tag.Attributes["href"] = urlHelper.Action(PageAction, PageUrlValues);
                        if(PageClassesEnabled)
                            {
                                tag.AddCssClass(PageClass);
                                tag.AddCssClass(i == PageModel.CurrentPage ?
                                    PageClassSelected : PageClassNormal);
                            }
                        tag.InnerHtml.Append(i.ToString());
                        result.InnerHtml.AppendHtml(tag);
                    }
                    output.Content.AppendHtml(result.InnerHtml);
                }
            }
        }


    Модели вот тут


    {
        public class PagingInfo
        {
            public int TotalItems { set; get; }
            public int ItemsPerPage { set; get; }
            public int CurrentPage { set; get; }
     
            public int TotalPages =>
                (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage);
        }
    }


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
     
    namespace SportStore2.Models.ViewModels
    {
        public class ProductsListViewModel
        {
            public IEnumerable<Product> Products { set; get; }
            public PagingInfo PagingInfo { set; get; }
            public string CurrentCategory { set; get; }
        }
    }



    public class Product
        {
            public int ProductID { set; get; }
            public string Name { set; get; }
            public string Decription { set; get; }
            public decimal Price { set; get; }
            public string category { set; get; }
        }

    Я уже само походу запутался и не могу понять почему когда кликаю по кнопкам которые обозначают категорию ничего не происходит, а должна выбираться нужная категория .Подскажите пожалуйста что я не так делаю?






    19 сентября 2018 г. 9:22

Все ответы

  • Привет!

    Подскажите пожалуйста что я не так делаю? 

    Много чего не так... 

    Во-первых: у вас есть книга в которой приведён не только рабочий код, но и описание того как это всё работает. То есть это как бы намёк на то, что всегда можно всё перепроверить и найти ошибку.

    Во-вторых: Где то в начале книги есть ссылка на полный исходный код всех примеров. В конечном счёте эта ссылка приведёт куда то сюда: https://github.com/Apress/pro-asp.net-core-mvc. Там есть полностью рабочий код! Можно всегда свериться с эталоном.

    Ошибки как минимум: в Startup.cs в маршрутах используется "productPage", хотя должно быть просто "page". В контроллере параметр "page" имеет значение по умолчанию 2, хотя должно быть 1 (на вторую страницу данных может просто не хватить и тогда она будет пустая).
    Дальше даже не вникал...

    ps: Работа программиста как минимум на 50% состоит из отладки и исправления ошибок. Так что такие простые ситуации как "правильно перепечатать код из книги", нужно решать самостоятельно, а не спрашивать на форуме, иначе ничему не научитесь.

    19 сентября 2018 г. 13:50