You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 6无刷新品牌筛选产品功能异常求助

无刷新产品筛选页面不更新问题排查

在ASP.NET Core 6的产品分类页面中,通过左侧侧边栏品牌复选框实现无刷新产品筛选,已使用Ajax避免页面重载。网络请求显示服务器已返回数据,但页面未正确更新,以下是相关代码及排查修复要点:

视图代码

@{
    ViewData["Title"] = "ProductCategory";
    Layout = "~/Views/Layout/_CategoryLayout.cshtml";
}
@{
    IEnumerable<Category> categories = ViewBag.Categories as IEnumerable<Category>;
    IEnumerable<Brand> brands = ViewBag.Brand as IEnumerable<Brand>;
    string currentUrl = Context.Request.GetDisplayUrl();
}
<input type="hidden" id="category-id" value="@Model.FirstOrDefault().CategoryId" />

<!-- SECTION -->
<div class="section">
    <!-- container -->
    <div class="container">
        <!-- row -->
        <div class="row">
            <!-- ASIDE -->
            <div id="aside" class="col-md-3">
                <!-- aside Widget -->
                <div class="aside">
                    <h3 class="aside-title">Brands</h3>
                    <div class="checkbox-filter">
                        @foreach (var item in brands)
                        {
                            <div class="input-checkbox">
                                <input type="checkbox" class="brand-checkbox" name="brand" id="@item.BrandId">
                                <label for="@item.BrandId">
                                    <span></span>
                                    @item.BrandName
                                    <small>(@item.Products.Count)</small>
                                </label>
                            </div>
                        }
                    </div>

                </div>
                <!-- /aside Widget -->
                <!-- aside Widget -->
                <div class="aside">
                    <h3 class="aside-title">Price</h3>
                    <div class="price-filter">
                        <div id="price-slider"></div>
                        <div class="input-number price-min">
                            <input id="price-min" type="number">
                            <span class="qty-up">+</span>
                            <span class="qty-down">-</span>
                        </div>
                        <span>-</span>
                        <div class="input-number price-max">
                            <input id="price-max" type="number">
                            <span class="qty-up">+</span>
                            <span class="qty-down">-</span>
                        </div>
                    </div>
                </div>
                <!-- /aside Widget -->
                
            </div>
            <!-- /ASIDE -->
            <!-- STORE -->
            <div id="store" class="col-md-9">
                <!-- store top filter -->
                <div class="store-filter clearfix">
                    <div class="store-sort">
                        @* <label>
                            Sort By:
                            <select class="input-select">
                                <option value="0">Popular</option>
                                <option value="1">Position</option>
                            </select>
                        </label>

                        <label>
                            Show:
                            <select class="input-select">
                                <option value="0">20</option>
                                <option value="1">50</option>
                            </select>
                        </label> *@
                    </div>
                    <ul class="store-grid">
                        <li class="active"><i class="fa fa-th"></i></li>
                        <li><a href="#"><i class="fa fa-th-list"></i></a></li>
                    </ul>
                </div>
                <!-- /store top filter -->
                <!-- store products -->
                <div class="row" id="product-list">
                    <!-- product -->
                    @foreach (var item in Model.Take(6))
                    {
                        <div class="col-md-4 col-xs-6">
                            <div class="product">
                                <a href="/post/@SlugGenerator.SlugGenerator.GenerateSlug(item.ProductName)-@item.ProductItems.FirstOrDefault().ProductVariations.FirstOrDefault().ProductVarId" />
                                <div class="product-img">

                                    <img src="~/Contents/img/@item.ProductItems.FirstOrDefault().Image1" width="200" height="200" alt="">
                                        <div class="product-label">
                                            <span class="sale">-30%</span>
                                            <span class="new">NEW</span>
                                        </div>
                                    </div>
                                    <div class="product-body">
                                    @*  <p class="product-category">@item.Category.CategoryName.ToUpper()</p> *@
                                        <h3 class="product-name"><a href="#">@item.ProductName.ToUpper()</a></h3>
                                        <h4 class="product-price">$@item.Price<del class="product-old-price">@* $@(item.Product.Price + 200) *@</del></h4>
                                        <div class="product-rating">
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                        </div>
                                        <div class="product-btns">
                                            <button class="add-to-wishlist"><i class="fa fa-heart-o"></i><span class="tooltipp">add to wishlist</span></button>
                                            <button class="add-to-compare"><i class="fa fa-exchange"></i><span class="tooltipp">add to compare</span></button>
                                            <button class="quick-view"><i class="fa fa-eye"></i><span class="tooltipp">quick view</span></button>
                                        </div>
                                    </div>
                    
                            </div>
                        </div>
                    }
                    <!-- /product -->
                </div>
                <!-- /store products -->
                <!-- store bottom filter -->
                <div class="store-filter clearfix">
                    <span class="store-qty">Showing 20-100 products</span>
                    <ul class="store-pagination">
                        <li class="active">1</li>
                        <li><a href="#">2</a></li>
                        <li><a href="#">3</a></li>
                        <li><a href="#">4</a></li>
                        <li><a href="#"><i class="fa fa-angle-right"></i></a></li>
                    </ul>
                </div>
                <!-- /store bottom filter -->
            </div>
            <!-- /STORE -->
        </div>
        <!-- /row -->
    </div>
    <!-- /container -->
</div>
<!-- /SECTION -->

Ajax代码

@section Scripts {
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            const checkboxes = document.querySelectorAll('.brand-checkbox');

            checkboxes.forEach((checkbox) => {
                checkbox.addEventListener('change', function () {
                    // 单选逻辑:每次仅保留当前选中的复选框
                    checkboxes.forEach((otherCheckbox) => {
                        if (otherCheckbox !== this) {
                            otherCheckbox.checked = false;
                        }
                    });

                    var selectedBrand = this.checked ? this.id : null;
                    var categoryId = $('#category-id').val();

                    $.ajax({
                        url: '@Url.Action("FilterByBrands", "ProductView")',
                        type: 'GET',
                        data: { brandid: selectedBrand, cateid: categoryId },
                        success: function (response) {
                            $('#product-list').html(response);
                        },
                        error: function(xhr, status, error) {
                            console.log(xhr.responseText);
                        }
                    });
                });
            });
        });
    </script>
}

控制器代码

[HttpGet]
public ActionResult FilterByBrands(int? brandid, int cateid)
{
    ViewBag.Brand = _context.Brands.Include(n => n.Products).ToList();

    IQueryable<Product> query = _context.Products
                          .Include(n => n.ProductItems)
                          .ThenInclude(n => n.ProductVariations)
                          .Include(n => n.Category)
                          .Where(n => n.CategoryId == cateid);

    if(brandid.HasValue)
    {
        query = query.Where(n => n.BrandNavigation.BrandId == brandid.Value);
    }

    var product = query.ToList();

    return PartialView("_FilterPartial", product);
}

关键修复点

  1. DOM选择器修正:原Ajax回调中使用$('#product'),但视图中无此id元素。给产品列表所在的.row容器添加id="product-list",并修改Ajax中的选择器为$('#product-list')。

  2. Partial视图精简:_FilterPartial视图仅需保留产品循环渲染代码(即主视图中<!-- product -->到<!-- /product -->之间的内容),不要包含完整页面结构,避免DOM重复混乱。

  3. 参数类型适配:将控制器的brandid改为int?可空类型,处理取消选中时前端传递的null值,同时调整查询逻辑,当brandid为空时返回该分类下所有产品。

  4. 错误调试补充:在Ajax中添加error回调,打印错误信息,便于排查请求异常。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:54:50