[回馈]ASP.NET Core MVC开发实战之商城系统(四)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面等功能的开发,今天继续讲解商品详情功能开发,仅供学习分享使用,如有不足之处,还请指正。

商品详情功能说明
首页和商品列表,都是只展示商品的主要信息,如商品名称,商品价格,类型等内容,让人有一个先入为主的商品概念,当用户对商品有兴趣时,可以点击链接跳转商品详情页面,查看商品更全面的信息,如:颜色,尺寸等内容。
商品详情功能设计
根据商品详情页面功能说明,在此页面,用户可以查看商品的具体内容,如:图片,颜色,大小,类型,标签以及加入购物车,立即购买等功能,具体页面设计如下所示:

商品详情页面功能开发
商品详情主要展示商品信息和商品配置信息。
1. 数据表创建
关于商品表EB_Product和对应模型Product的创建,可参考第二篇文章。商品配置表EB_ProductConfig,主要配置商品的特殊属性,如:颜色,尺寸,缩略图等内容,如下所示:

创建表的语句,如下所示:
CREATE TABLE [dbo].[EB_ProductConfig]([Id] [bigint] IDENTITY(1,1) NOT NULL,[ProductId] [bigint] NULL,[ConfigType] [varchar](50) NULL,[ConfigName] [varchar](50) NULL,[ConfigValue] [varchar](150) NULL,[CreateTime] [datetime] NULL,[CreateUser] [varchar](50) NULL,[LastEditTime] [datetime] NULL,[LastEditUser] [varchar](50) NULL
) ON [PRIMARY]
2. 商品配置实体创建
商品配置表对应的项目模型实体,和数据表一一对应,如下所示:
namespace EasyBuyShop.Models
{/// <summary>/// 产品配置,主要配置颜色,大小,缩略图路径等/// </summary>[SqlSugar.SugarTable("EB_ProductConfig")]public class ProductConfig : EntityModel{public long ProductId { get; set; }public string ConfigType { get; set; }public string ConfigName { get; set; }public string ConfigValue { get; set; }}
}
3. 数据处理层DAL
商品详情页面主要根据商品ID获取商品的详细信息以及商品配置信息,如下所示:
商品详细信息在ProductDal中,如下所示:
public Product GetProduct(long Id)
{try{using (var db = this.GetDb(BaseDal.ConnStr)){return db.Queryable<Product>().First(r=>r.Id==Id);}}catch (Exception ex){LogHelper.Fatal(ex.Message);return null;}
}
商品配置信息在ProductConfigDal中,获取配置信息如下所示:
using EasyBuyShop.Models;
using EasyBuyShop.Utils;namespace EasyBuyShop.DAL
{public class ProductConfigDal : BaseDal{public ProductConfigDal(){}/// <summary>/// 获取产品配置/// </summary>/// <param name="productId"></param>/// <returns></returns>public List<ProductConfig> GetProductConfigListById(long productId){try{using (var db = this.GetDb(BaseDal.ConnStr)){return db.Queryable<ProductConfig>().Where(r => r.ProductId == productId).ToList();}}catch (Exception ex){LogHelper.Fatal(ex.Message);return new List<ProductConfig>();}}}
}
4. 控制器获取
商品详细信息在ProductController的Detail方法中,根据传入的ID进行读取,如下所示:
public IActionResult Detail(int Id)
{var username = HttpContext.Session.GetString("username");var realName = HttpContext.Session.GetString("realname");ViewData["Username"] = username;ViewData["RealName"] = realName;ProductDal productDal = new ProductDal();ProductConfigDal productConfigDal = new ProductConfigDal();var product = productDal.GetProduct(Id);var productConfigList = productConfigDal.GetProductConfigListById(Id);ViewData["ProductConfigList"]=productConfigList;ViewData["Product"] = product;return View();
}
将获取到的Product对象和ProductConfigList列表对象通过ViewData传递到View视图层中进行展示。
5. 视图层展示
在Views/Product/Detail.cshtml中,接收控制器方法传递的数据,并进行展示。如下所示:
@{ViewData["Title"] = "商品详情";
}
@{var product = ViewData["Product"] as Product;var productConfigList = ViewData["ProductConfigList"] as List<ProductConfig>;
}
<div class=""><form method="post" id="detailForm"><input type="hidden" name="productId" value="@(product.Id)" /><input type="hidden" name="color" id="color" value="" /><input type="hidden" name="size" id="size" value="" /><!-- quick view start --><div class="container"><div class="row"><div id="view-gallery"><div class="col-xs-12"><div class="d-table" style="width:100%"><div class="d-tablecell"><div class="main-view modal-content"><div class="row"><div class="col-xs-12 col-sm-5"><div class="quick-image"><div class="single-quick-image tab-content text-center">@{var productConfigImages = productConfigList.Where(r => r.ConfigType == "Image").ToList();for (int i = 0; i < productConfigImages.Count; i++){var productConfigImage = productConfigImages[i];<div class="tab-pane fade in @(i==0?"active":"")" id="sin-pro-@(i)"><img src="@(productConfigImage.ConfigValue)" alt=""></div>}}</div><div class="quick-thumb"><div class="nav nav-tabs"><ul style="padding-left:0px;">@{for (int i = 0; i < productConfigImages.Count; i++){var productConfigImage = productConfigImages[i];<li><a data-toggle="tab" href="##" onclick="javascript:tabProductImage('sin-pro-@(i)',this);"> <img src="@(productConfigImage.ConfigName)" alt="quick view" style="width:90px;height:90px;"> </a></li>}}</ul></div></div></div></div><div class="col-xs-12 col-sm-7"><div class="quick-right"><div class="quick-right-text"><h3><strong>@product.Name</strong></h3><div class="rating"><i class="fa fa-star"></i><i class="fa fa-star"></i><i class="fa fa-star"></i><i class="fa fa-star-half-o"></i><i class="fa fa-star-o"></i></div><div class="amount"><h4>$@product.PreferentialPrice</h4></div><p>@product.Description</p><div class="row m-p-b"><div class="col-sm-12"><div class="por-dse responsive-strok clearfix"><ul><li><span>是否现货</span><strong>:</strong> 现货</li><li><span>是否新品</span><strong>:</strong> 新品</li><li><span>商品类型</span><strong>:</strong><a href="">@product.BasicStyle</a><a href="">@product.ProductStyle</a></li></ul></div></div></div><div class="row m-p-b"><div class="col-sm-12"><div class="por-dse color"><ul><li><span>颜色分类</span><strong>:</strong><div class="por-dsc-div">@{var productColors = productConfigList.Where(r => r.ConfigType == "Color").ToList();for (int i = 0; i < productColors.Count; i++){<span class="por-dsc-span" onclick="javascript:checkActive(this,'color');">@(productColors[i].ConfigValue)</span>}}</div></li><li><span>大小</span><strong>:</strong><div class="por-dsc-div">@{var productSizes = productConfigList.Where(r => r.ConfigType == "Size").ToList();for (int i = 0; i < productSizes.Count; i++){<span class="por-dsc-span" onclick="javascript:checkActive(this,'size');">@(productSizes[i].ConfigValue)</span>}}</div></li><li><span>标签</span><strong>:</strong><a href="">@product.BasicStyle</a><a href="">@product.ProductStyle</a></li></ul></div></div></div><div class="dse-btn"><div class="row"><div class="col-sm-12 col-md-12"><div class="por-dse clearfix"><ul><li class="share-btn clearfix"><span>数量</span><input class="input-text qty" name="quantity" maxlength="12" value="1" title="数量" type="text"></li></ul></div></div><div class="col-sm-12 col-md-12"><div class="por-dse add-to" style="display:inline-block"><a href="##" onclick="javascript:addCartByForm();">加入购物车</a></div><div class="por-dse add-to" style="display:inline-block"><a href="##" onclick="javascript:addPurchaseByForm();">立即购买</a></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><!-- quick view end --></form>
</div>
<script src="~/js/shop.js"></script>
商品详情页面展示
运行程序,在首页或商品列表页面,点击商品链接,进入商品详情页面,如下所示:

以上就是ASP.NET Core MVC开发实战之商城系统第四部分内容,后续将继续介绍其他模块,敬请期待。
相关文章:
[回馈]ASP.NET Core MVC开发实战之商城系统(四)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,ba…...
Vue.js常见错误处理包含代码
目录 以下是 Vue.js 中常见的错误,以及相应的处理方法和代码示例: 语法错误 错误信息:Error: [vm] "name" is not defined 解决方法:确保组件的 data 中定义了相同的属性。 示例代码: <template> &l…...
Go项目实现日志按时间及文件大小切割并压缩
关于日志的一些问题: 单个文件过大会影响写入效率,所以会做拆分,但是到多大拆分? 最多保留几个日志文件?最多保留多少天,要不要做压缩处理? 一般都使用 lumberjack[1]这个库完成上述这些操作 lumberjack //info文件wr…...
容器化的好处
容器化,是指使用容器技术(Docker/containerd等)运行应用程序(容器),并使用容器编排技术(例如 K8s)来管理这些容器。 我在之前的文章 《使用 Dockerfile 构建生产环境镜像》 提及普通…...
TPlink DDNS 内网穿透?外网访问设置方法
有很多小伙伴都想知道:TPlink路由器怎么设置DDNS内网穿透?今天,小编就给大家分享一下TPlink DDNS 外网访问设置方法,下面是图文教程,帮助新手快速入门DDNS设置。 本文介绍的是云路由器TP-LINK DDNS的设置方法。TP-LIN…...
以CS32F031为例浅说国产32位MCU的内核处理器
芯片内核又称CPU内核,它是CPU中间的核心芯片,是CPU最重要的组成部分。由单晶硅制成,CPU所有的计算、接受/存储命令、处理数据都由核心执行。各种CPU核心都具有固定的逻辑结构,一级缓存、二级缓存、执行单元、指令级单元和总线接口…...
享元模式(Flyweight)
享元模式是一种结构型设计模式,主要通过共享技术有效地减少大量细粒度对象的复用,以减少内存占用和提高性能。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式。 Flyweight is a structural pattern, which effecti…...
Cilium系列-11-启用带宽管理器
系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, 可以进一步提升 Cilium 的网络性能. 具体调优项包括不限于: 启用本地路由(Native Routing)完全替换 KubeProx…...
无人机自动返航的关键技术有哪些
无人机的广泛应用使得无人机自动返航技术变得至关重要。在各种应对意外情况的背景下,无人机自动返航技术的发展对确保无人机的安全,以及提高其应用范围具有重要意义。接下来,便为大家详细介绍无人机自动返航所运用到的关键技术。 一、定位与导…...
Vision Transformer (ViT):图像分块、图像块嵌入、类别标记、QKV矩阵与自注意力机制的解析
作者:CSDN _养乐多_ 本文将介绍Vision Transformers (ViT)中的关键点。包括图像分块(Image Patching)、图像块嵌入(Patch Embedding)、类别标记、(class_token)、QKV矩…...
Mybatis:一对多映射处理
Mybatis:一对多映射处理 前言一、概述二、创建数据模型三、问题四、解决方案1、方案一:collection(嵌套结果)2、方案二:分步查询(嵌套查询) 前言 本博主将用CSDN记录软件开发求学之路上的亲身所…...
HTML+CSS+JavaScript:全选与反选案例
一、需求 1、单击全选按钮,下面三个复选框自动选中,再次单击全选按钮,下面三个复选框自动取消选中 2、当下面三个复选框全都选中时,全选按钮自动选中,下面三个复选框至少有一个未选中,全选按钮自动取消选…...
Python 程序设计入门(001)—— 安装 Python(Windows 操作系统)
Python 程序设计入门(001)—— 安装 Python(Windows 操作系统) 目录 Python 程序设计入门(001)—— 安装 Python(Windows 操作系统)一、下载 Python 安装包二、安装 Python三、测试&…...
【redis】创建集群
这里介绍的是创建redis集群的方式,一种是通过create-cluster配置文件创建部署在一个物理机上的伪集群,一种是先在不同物理机启动单体redis,然后通过命令行使这些redis加入集群的方式。 一,通过配置文件创建伪集群 进入redis源码…...
linux 配置nacos遇见的问题及解决办法
本次的集群是启动一个服务的三个不同端口,配置如下: 一.application.properties 加上下列配置,目的是使用自己的mysql数据库: spring.datasource.platformmysql db.num1 db.url.0jdbc:mysql://127.0.0.1:3306/nacos_config?s…...
小程序开发趋势:探索人工智能在小程序中的应用
第一章:引言 小程序开发近年来取得了快速的发展,成为了移动应用开发的重要一环。随着人工智能技术的飞速发展,越来越多的企业开始探索如何将人工智能应用于小程序开发中,为用户提供更智能、便捷的服务。本文将带您一起探索人工智能…...
基于埋点日志数据的网络流量统计 - PV、UV
水善利万物而不争,处众人之所恶,故几于道💦 文章目录 一、 网站总流量数统计 - PV 1. 需求分析 2. 代码实现 方式一 方式二 方式三:使用process算子实现 方式四:使用process算子实现 二、网站独立访客数统计 - UV 1. …...
cuda入门demo(2)——最基础的二方向sobel
⚠️主要是自己温习用,只保证代码正确性,不保证讲解的详细性。 今天继续总结cuda最基本的入门demo。很多教程会给你说conv怎么写,实际上sobel也是conv,并且conv本身已经用torch实现了。 之前在课题中尝试了sobel的变体࿰…...
软件外包开发的后台开发语言
在软件外包开发中,后台语言的选择通常取决于项目需求、客户偏好、团队技能和开发效率。今天和大家分享一些常用的后台语言及选择它们的原因,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。…...
自动驾驶感知系统-全球卫星定位系统
卫星定位系统 车辆定位是让无人驾驶汽车获取自身确切位置的技术,在自动驾驶技术中定位担负着相当重要的职责。车辆自身定位信息获取的方式多样,涉及多种传感器类型与相关技术。自动驾驶汽车能够持续安全可靠运行的一个关键前提是车辆的定位系统必须实时…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
