机器翻译正文由机器翻译自项目原始文档(英文),排版经程序统一处理,可能存在偏差,请以原项目仓库为准。
这是一个基于实际 电子商务网页应用程序 项目中 aspnetrun-core 基础 的 实现;
AspnetRunCoreRealWorld 是基于 aspnetrun 项目的一个实现,使用 清晰架构 和最佳实践编写。其理念是展示 如何在基础仓库上实现真实项目,即使用完整 E&E 电子商务网页模板 实现的 电子商务领域。AspnetRunRealWorld 是一个使用 Northwind 数据库 实现的 电子商务领域 实例。它采用 分层架构 管理,用于构建基于最新 ASP.NET Core、Web API 和 EF Core 技术的现代网页应用程序。
本仓库包含的内容
我们已经在 run-aspnetcore 模板上实现了以下 功能。您可以根据您的业务需求更改 实际功能;
- E&E 电商主题实现
- Northwind 数据库的电商用例完整开发
- 业务规则检查、领域策略应用和验证
- 身份验证、身份模块及身份配置
- 产品页面的授权
- Asp.net core 内置依赖注入
- Aspnet core Razor 工具 - 视图组件、局部视图、标签助手、模型绑定与验证、Razor 区块等
- 配置管理
- 自定义分页实现
我们还有很多 缺失的功能,您可以在 我们的项目页面 查看并进行开发。我们期待您的 pull request。
给个星星! :star:
如果您喜欢这个项目,或者 AspnetRun 对您有帮助,请 给一个星标。同时请 fork 这个仓库并给我们发送 pull request。如果发现任何问题,请打开 issue。
入门指南
使用这些说明来启动和运行项目。
前提条件
您将需要以下工具:
- Visual Studio 2019
- .Net Core 3.x or later
- EF Core 3.x 或更高版本
安装
按照以下步骤设置您的开发环境:
- 克隆代码仓库
- 在根目录下运行以下命令以恢复所需的包:
dotnet restore - 接下来,通过运行以下命令来构建解决方案:
dotnet build - 接下来,在 AspnetRun.Web 目录中,通过运行以下命令启动后端:
dotnet run - 在浏览器中启动 http://localhost:5400/ 以查看 Web UI。
如果你在克隆后拥有 Visual Studio,请使用你的 IDE 打开解决方案,AspnetRun.Web 应该是启动项目。直接在 Visual Studio 中使用 F5 或 Ctrl F5 运行该项目。你将看到项目的首页,可以浏览产品和分类页面,并且可以在浏览器中执行 CRUD 操作。
用法
在克隆或下载示例后,你应该能够立即使用内存数据库运行它。Entity Framework 数据库的默认配置是 "InMemoryDatabase"。如果你希望使用持久数据库运行该项目,你需要在运行应用程序之前执行其 Entity Framework Core 迁移,并在 Startup.cs 中更新 ConfigureDatabases 方法(见下文)。
public void ConfigureDatabases(IServiceCollection services)
{
// use in-memory database
services.AddDbContext<AspnetRunContext>(c =>
c.UseInMemoryDatabase("AspnetRunConnection")
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
//// use real database
//services.AddDbContext<AspnetRunContext>(c =>
// c.UseSqlServer(Configuration.GetConnectionString("AspnetRunConnection"))
// .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
}
-
确保
appsettings.json中的连接字符串指向本地 SQL Server 实例。 -
在 Web 文件夹中打开命令提示符并执行以下命令:
dotnet restore
dotnet ef database update -c AspnetRunContext -p ../AspnetRun.Infrastructure/AspnetRun.Infrastructure.csproj -s AspnetRun.Web.csproj
或者你可以直接从 Visual Studio 包管理器控制台 调用 ef 命令。打开包管理器控制台,将默认项目设置为 AspnetRun.Infrastructure,然后运行以下命令;
update-database
这些命令将创建包含 Product 和 Category 表的 aspnetrun 数据库。你可以从 AspnetRunContext.cs 中看到。
- 运行应用程序。第一次运行应用程序时,它将向 aspnetrun SQL Server 数据库添加一些数据,这样你就可以看到产品和类别。
如果你修改、更改或向 Core 项目添加了一些实体,你应该运行 ef migrate 命令以以相同方式更新数据库,但使用以下命令;
add migration YourCustomEntityChanges
update-database
分层架构
AspnetRun 实现了 NLayer 六边形架构(核心层、应用层、基础设施层和表示层)和 领域驱动设计(实体、仓储、领域/应用服务、DTO 等)。同时,它还实现并提供了良好的基础设施来执行 最佳实践,如依赖注入、日志记录、验证、异常处理、本地化等。旨在成为 清洁架构(也称 洋葱架构),并应用 SOLID 原则,以用于项目模板。同时,它还实现并提供了良好的基础设施来执行 最佳实践,例如 低耦合、依赖倒置 的架构。下面的图片展示了 aspnetrun 的开发架构方法,用于运行仓储系列;
项目结构
仓储包含按 4 个项目 划分的层;
- 核心层
- Entities
- Interfaces
- Specifications
- ValueObjects
- Exceptions
- 应用层
- Interfaces
- Services
- Dtos
- Mapper
- Exceptions
- 基础设施层
- Data
- Repository
- Services
- Migrations
- Logging
- Exceptions
- Web 层
- Interfaces
- Services
- Pages
- ViewModels
- Extensions
- Mapper
核心层
通过抽象开发领域逻辑。接口以轻量实现驱动业务需求。核心项目是 清洁架构 设计的 中心,所有其他项目的依赖都应指向它。
实体
包含使用 Entity Framework Core 代码优先方法 创建 SQL 表的实体框架实体。一些聚合文件夹保存实体和聚合。您可以在下面看到 代码优先 的实体定义示例;
public class Product : BaseEntity
{
public string ProductName { get; set; }
public string QuantityPerUnit { get; set; }
public decimal? UnitPrice { get; set; }
public short? UnitsInStock { get; set; }
public short? UnitsOnOrder { get; set; }
public short? ReorderLevel { get; set; }
public bool Discontinued { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public static Product Create(int productId, int categoryId, string name, decimal? unitPrice = null, short? unitsInStock = null, short? unitsOnOrder = null, short? reorderLevel = null, bool discontinued = false)
{
var product = new Product
{
Id = productId,
CategoryId = categoryId,
ProductName = name,
UnitPrice = unitPrice,
UnitsInStock = unitsInStock,
UnitsOnOrder = unitsOnOrder,
ReorderLevel = reorderLevel,
Discontinued = discontinued
};
return product;
}
}
采用领域驱动方法,Product 类负责创建 Product 实例。
接口
仓储抽象 - 领域仓储 (IAsyncRepository - IProductRepository) - 规格等。这些接口包括数据库操作,而不涉及任何应用程序和 UI 责任。
规格
此文件夹是 规格模式 的实现。使用 ISpecification 接口创建自定义脚本。使用 BaseSpecification 管理 Criteria、Includes、OrderBy、Paging。这些规格在 EF 命令执行时被调用,并传递规格。规格通过 SpecificationEvaluator.cs 实现,并在 ApplySpecification 方法中为 AspnetRunRepository.cs 创建查询。这有助于创建自定义查询。
基础设施层
在本项目中使用 Entity Framework Core 和其他依赖实现核心接口。大多数应用程序对外部资源的依赖应在基础设施项目中定义的类中实现。这些类必须实现 Core 中定义的接口。如果你的项目非常大且依赖项众多,可能需要多个基础设施项目(例如 Infrastructure.Data),但在大多数项目中,一个包含文件夹的基础设施项目即可。例如,这可以包括 电子邮件提供者、文件访问、Web API 客户端 等。目前此存储库仅依赖示例数据访问和基本域操作,因此不会与核心或 UI 项目直接关联。
数据
包括 Entity Framework Core 上下文 和本文件夹中的表。创建新实体时,应将其添加到上下文并在上下文中进行配置。基础设施项目依赖于 Microsoft.EntityFrameworkCore.SqlServer 和 EF.Core 相关的 nuget 包,可以检查基础设施层的 nuget 包。如果要更改数据访问层,可以轻松替换为更轻量级的 ORM,如 Dapper。
迁移
EF 添加迁移类。
仓储
EF 仓储和规格实现。此类负责创建查询、包含关系、where 条件等。
服务
自定义服务实现,如电子邮件、定时任务等。
应用层
领域逻辑的开发及实现。接口驱动业务需求和此层的实现。应用层定义用户在应用服务类中所需的操作如下所示;
public interface IProductAppService
{
Task<IEnumerable<ProductDto>> GetProductList();
Task<ProductDto> GetProductById(int productId);
Task<IEnumerable<ProductDto>> GetProductByName(string productName);
Task<IEnumerable<ProductDto>> GetProductByCategory(int categoryId);
Task<ProductDto> Create(ProductDto entityDto);
Task Update(ProductDto entityDto);
Task Delete(ProductDto entityDto);
}
实现也位于相同的位置,以便在依赖注入启动时选择不同的实现。
public class ProductAppService : IProductAppService
{
private readonly IProductRepository _productRepository;
private readonly IAppLogger<ProductAppService> _logger;
public ProductAppService(IProductRepository productRepository, IAppLogger<ProductAppService> logger)
{
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<IEnumerable<ProductDto>> GetProductList()
{
var productList = await _productRepository.GetProductListAsync();
var mapped = ObjectMapper.Mapper.Map<IEnumerable<ProductDto>>(productList);
return mapped;
}
}
在此层中,我们可以添加验证、授权、日志记录、异常处理等——横切活动应在此处处理。
Web 层
开发带有实现的 UI 逻辑。接口在此层中驱动业务需求和实现。应用程序的主要起点是 ASP.NET Core Web 项目。这是一个经典的控制台应用程序,在 Program.cs 中有一个公共静态 void Main 方法。目前它使用基于Razor Pages 模板的默认ASP.NET Core 项目模板。这包括 appsettings.json 文件以及环境变量以存储配置参数,并在 Startup.cs 中进行配置。
Web 层定义了页面服务类中用户所需的操作,如下所示;
public interface IProductPageService
{
Task<IEnumerable<ProductViewModel>> GetProducts(string productName);
Task<ProductViewModel> GetProductById(int productId);
Task<IEnumerable<ProductViewModel>> GetProductByCategory(int categoryId);
Task<IEnumerable<CategoryViewModel>> GetCategories();
Task<ProductViewModel> CreateProduct(ProductViewModel productViewModel);
Task UpdateProduct(ProductViewModel productViewModel);
Task DeleteProduct(ProductViewModel productViewModel);
}
实现也位于相同的位置,以便在依赖注入启动时选择不同的实现。
public class ProductPageService : IProductPageService
{
private readonly IProductAppService _productAppService;
private readonly ICategoryAppService _categoryAppService;
private readonly IMapper _mapper;
private readonly ILogger<ProductPageService> _logger;
public ProductPageService(IProductAppService productAppService, ICategoryAppService categoryAppService, IMapper mapper, ILogger<ProductPageService> logger)
{
_productAppService = productAppService ?? throw new ArgumentNullException(nameof(productAppService));
_categoryAppService = categoryAppService ?? throw new ArgumentNullException(nameof(categoryAppService));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<IEnumerable<ProductViewModel>> GetProducts(string productName)
{
if (string.IsNullOrWhiteSpace(productName))
{
var list = await _productAppService.GetProductList();
var mapped = _mapper.Map<IEnumerable<ProductViewModel>>(list);
return mapped;
}
var listByName = await _productAppService.GetProductByName(productName);
var mappedByName = _mapper.Map<IEnumerable<ProductViewModel>>(listByName);
return mappedByName;
}
}
测试层
每个层都有一个测试项目,包含预期的层依赖和模拟类。这意味着核心-应用-基础设施和网页层各自有自己的测试层。通过这种方式,这些测试项目也按实现的层定义的单元测试、功能和集成测试划分。测试项目使用xunit和模拟库。xunit,因为 ASP.NET Core内部用它测试产品。Moq,因为它能清晰地创建假对象,且非常模块化。
技术
- .NET Core 3.x
- ASP.NET Core 3.x
- 实体框架 Core 3.x
- .NET Core 原生依赖注入
- Razor 页面
- AutoMapper
架构
- 清洁架构
- 具有关注点分离责任的完整架构
- SOLID 和清洁代码
- 领域驱动设计(分层和领域模型模式)
- 工作单元
- 仓储和通用仓储
- 多页面 Web 应用程序(MPA)
- 单体部署架构
- 规范模式
免责声明
- 本仓库不打算成为最终解决方案。
- 本仓库未实现很多第三方包,我们在基于最佳实践构建时尽量避免过度工程。
- 在生产环境中使用时请注意。
贡献
请阅读 Contributing.md 了解我们的行为准则,以及向我们提交拉取请求的流程。我们有很多缺失的功能,你可以在 我们的项目页面 查看,并进行开发。我们在等待你的拉取请求。
版本控制
我们使用 SemVer 进行版本管理。有关可用版本,请参阅此存储库上的 标签。
下一版本和路线图
有关即将推出的功能和修复的信息,请查看产品路线图。
部署 - AspnetRun 在线
该项目已部署在 Azure 上。请在此处查看在 Azure 上运行的项目。
拉取请求
请分叉这个仓库,并通过拉取请求将您的发现发送给我。这是一个开源仓库,因此欢迎贡献。您可以从我们的项目页面的缺失功能 这里 获取您的项目,并向我们发送拉取请求。
作者
- Mehmet Ozkaya - 初步工作 - mehmetozkaya
另请参阅参与此项目的贡献者名单。
许可证
本项目采用 MIT 许可证 - 详情请参阅 LICENSE.md 文件
- 本文标题:run-aspnetcore-realworld - 运行 ASP.NET Core ASP.NET Co
- 本文链接:https://www.cn121.com/shop/aspnetrun-run-aspnetcore-realworld.html
- 原项目:aspnetrun/run-aspnetcore-realworld 版权归原作者 aspnetrun 及贡献者所有
- 收录信息:本站于 2026-10-25 收录本项目,本页所列协议与仓库指标均为收录当时的状态;该日期之后原项目的版本更新与协议变更,本页不作同步。
- 开源协议:收录时本项目采用 MIT(查看 LICENSE 原文),本站译文为其衍生内容;使用、修改、分发请以该仓库 LICENSE 原文为准。
- 站点出处:本文首发于 OneTwoOne,收录自 GitHub 开源项目 aspnetrun/run-aspnetcore-realworld。
- 翻译说明:本页正文为人工智能生成内容——由机器翻译对原项目 README 初译、经程序校验排版,可能存在错漏,请以原项目文档为准。
- 引用声明:商业转载、第三方聚合或 AI 检索训练引用时,请务必保留以上来源出处、本文永久链接,以及原项目的版权声明与许可信息。
- 下架通道:若原项目此后变更或收紧了许可协议、或作者/权利人认为本站的收录方式(译文、排版适配、简介翻译等)超出其授权范围,请通过 xyd3302001@163.com 发送下架通知,并附上项目地址与本页链接。本站核实后将第一时间删除本页内容,或改为不复制原文的目录性收录;署名更正等其他要求可一并提出。