ASP.NET样板开发框架ABP系列之ABP入门教程详解

abp是为新的现代web应用程序使用最佳实践和使用最流行工具的一个起点。可作为一般用途的应用程序的基础框架或项目模板。接下来通过本文给大家详细介绍abp入门教程,感兴趣的朋友一起看看吧

ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。

ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。

ABP的官方网站:http://www.aspnetboilerplate.com

ABP在Github上的开源项目:https://github.com/aspnetboilerplate

ABP 的由来

“DRY——避免重复代码”是一个优秀的开发者在开发软件时所具备的最重要的思想之一。我们在开发企业WEB应用程序时都有一些类似的需求,例如:都需要登录页面、用户/角色管理、权限验证、数据有效性验证、多语言/本地化等等。一个高品质的大型软件都会运用一些最佳实践,例如分层体系结构、领域驱动设计、依赖注入等。我们也可能会采用ORM、数据库迁移(Database Migrations)、日志记录(Logging)等工具。

从零开始创建一个企业应用程序是一件繁琐的事,因为需要重复做很多常见的基础工作。许多公司都在开发自己的应用程序框架来重用于不同的项目,然后在框架的基础上开发一些新的功能。但并不是每个公司都有这样的实力。假如我们可以分享的更多,也许可以避免每个公司或每个项目的重复编写类似的代码。作者之所以把项目命名为“ASP.NET Boilerplate”,就是希望它能成为开发一般企业WEB应用的新起点,直接把ABP作为项目模板。

ABP是什么?

ABP是为新的现代Web应用程序使用最佳实践和使用最流行工具的一个起点。可作为一般用途的应用程序的基础框架或项目模板。它的功能包括:

服务器端:

基于最新的.NET技术 (目前是ASP.NET MVC 5、Web API 2、C# 5.0,在ASP.NET 5正式发布后会升级)

实现领域驱动设计(实体、仓储、领域服务、领域事件、应用服务、数据传输对象,工作单元等等)

实现分层体系结构(领域层,应用层,展现层和基础设施层)提供了一个基础架构来开发可重用可配置的模块集成一些最流行的开源框架/库,也许有些是你正在使用的。

提供了一个基础架构让我们很方便地使用依赖注入(使用Castle Windsor作为依赖注入的容器)

提供Repository仓储模式支持不同的ORM(已实现Entity Framework 、NHibernate、MangoDb和内存数据库)

支持并实现数据库迁移(EF 的 Code first)模块化开发(每个模块有独立的EF DbContext,可单独指定数据库)

包括一个简单的和灵活的多语言/本地化系统

包括一个 EventBus来实现服务器端全局的领域事件统一的异常处理(应用层几乎不需要处理自己写异常处理代码)

数据有效性验证(Asp.NET MVC只能做到Action方法的参数验证,ABP实现了Application层方法的参数有效性验证)

通过Application Services自动创建Web Api层(不需要写ApiController层了)

提供基类和帮助类让我们方便地实现一些常见的任务

使用“约定优于配置原则”

客户端:

Bootstrap、Less、AngularJs、jQuery、Modernizr和其他JS库: jQuery.validate、jQuery.form、jQuery.blockUI、json2等

为单页面应用程序(AngularJs、Durandaljs)和多页面应用程序(Bootstrap+Jquery)提供了项目模板。

自动创建Javascript 的代理层来更方便使用Web Api封装一些Javascript 函数,更方便地使用ajax、消息框、通知组件、忙状态的遮罩层等等

除ABP框架项目以外,还开发了名叫“Zero”的模块,实现了以下功能:

身份验证与授权管理(通过ASP.NET Identity实现的)

用户&角色管理系统设置存取管理(系统级、租户级、用户级,作用范围自动管理)

审计日志(自动记录每一次接口的调用者和参数)

ABP不是什么?

ABP提供了一个应用程序开发模型用于最佳实践。它拥有基础类、接口和工具使我们容易建立起可维护的大规模的应用程序。

然而:

它不是RAD工具之一,RAD工具的目的是无需编码创建应用程序。相反,ABP提供了一种编码的最佳实践。

它不是一个代码生成工具。在运行时虽然它有一些特性构建动态代码,但它不能生成代码。

它不是一个一体化的框架。相反,它使用流行的工具/库来完成特定的任务(例如用EF做ORM,用Log4Net做日志记录,使得Castle Windsor作为赖注入容器, AngularJs 用于SPA 框架)。

就我使用了ABP几个月的经验来看,虽然ABP不是RAD,但是用它开发项目绝对比传统三层架构要快很多。

虽然ABP不是代码生成工具,但因为有了它,使我们项目的代码更简洁规范,这有利于使用代码生成工具。

我自己使用VS2013的Scaffolder+T4开发的代码生成器,可根据领域对象的UML类图自动生成全部前后端代码和数据库,简单的CURD模块几乎不需要编写代码,有复杂业务逻辑的模块主要补充领域层代码即可。这样就能把时间多花在领域模型的设计上,减少写代码的时间。

下面通过原作者的“简单任务系统”例子,演示如何运用ABP开发项目

从模板创建空的web应用程序

ABP提供了一个启动模板用于新建的项目(尽管你能手动地创建项目并且从nuget获得ABP包,模板的方式更容易)。

转到www.aspnetboilerplate.com/Templates从模板创建你的应用程序。

ASP.NET样板开发框架ABP系列之ABP入门教程详解

你可以选择SPA(AngularJs或DurandalJs)或者选择MPA(经典的多页面应用程序)项目。可以选择Entity Framework或NHibernate作为ORM框架。

这里我们选择AngularJs和Entity Framework,填入项目名称“SimpleTaskSystem”,点击“CREATE MY PROJECT”按钮可以下载一个zip压缩包,解压后得到VS2013的解决方案,使用的.NET版本是 4.5.1。

ASP.NET样板开发框架ABP系列之ABP入门教程详解

每个项目里引用了Abp组件和其他第三方组件,需要从Nuget下载。

ASP.NET样板开发框架ABP系列之ABP入门教程详解

黄色感叹号图标,表示这个组件在本地文件夹中不存在,需要从Nuget上还原。操作如下:

ASP.NET样板开发框架ABP系列之ABP入门教程详解

ASP.NET样板开发框架ABP系列之ABP入门教程详解

要让项目运行起来,还得创建一个数据库。这个模板假设你正在使用SQL2008或者更新的版本。当然也可以很方便地换成其他的关系型数据库。

打开Web.Config文件可以查看和配置链接字符串:


登录后复制

(在后面用到EF的Code first数据迁移时,会自动在SQL Server数据库中创建一个名为SimpleTaskSystemDb的数据库。)

就这样,项目已经准备好运行了!打开VS2013并且按F5:

ASP.NET样板开发框架ABP系列之ABP入门教程详解

下面将逐步实现这个简单的任务系统程序

创建实体

把实体类写在Core项目中,因为实体是领域层的一部分。

一个简单的应用场景:创建一些任务(tasks)并分配给人。 我们需要Task和Person这两个实体。

Task实体有几个属性:描述(Description)、创建时间(CreationTime)、任务状态(State),还有可选的导航属性(AssignedPerson)来引用Person。

public class Task : Entity{ [ForeignKey("AssignedPersonId")] public virtual Person AssignedPerson { get; set; } public virtual int? AssignedPersonId { get; set; } public virtual string Description { get; set; } public virtual DateTime CreationTime { get; set; } public virtual TaskState State { get; set; } public Task() {  CreationTime = DateTime.Now;  State = TaskState.Active; }}

登录后复制

Person实体更简单,只定义了一个Name属性:

public class Person : Entity{ public virtual string Name { get; set; }}

登录后复制

在ABP框架中,有一个Entity基类,它有一个Id属性。因为Task类继承自Entity,所以它有一个long类型的Id。Person类有一个int类型的Id,因为int类型是Entity基类Id的默认类型,没有特别指定类型时,实体的Id就是int类型。

创建DbContext

使用EntityFramework需要先定义DbContext类,ABP的模板已经创建了DbContext文件,我们只需要把Task和Person类添加到IDbSet,请看代码:

public class SimpleTaskSystemDbContext : AbpDbContext{ public virtual IDbSet Tasks { get; set; } public virtual IDbSet People { get; set; } public SimpleTaskSystemDbContext()  : base("Default") { } public SimpleTaskSystemDbContext(string nameOrConnectionString)  : base(nameOrConnectionString) {    }}

登录后复制

通过Database Migrations创建数据库表

我们使用EntityFramework的Code First模式创建数据库架构。ABP模板生成的项目已经默认开启了数据迁移功能,我们修改SimpleTaskSystem.EntityFramework项目下Migrations文件夹下的Configuration.cs文件:

internal sealed class Configuration : DbMigrationsConfiguration{ public Configuration() {  AutomaticMigrationsEnabled = false; } protected override void Seed(SimpleTaskSystem.EntityFramework.SimpleTaskSystemDbContext context) {  context.People.AddOrUpdate(   p => p.Name,   new Person {Name = "Isaac Asimov"},   new Person {Name = "Thomas More"},   new Person {Name = "George Orwell"},   new Person {Name = "Douglas Adams"}   ); }}

登录后复制

在VS2013底部的“程序包管理器控制台”窗口中,选择默认项目并执行命令“Add-Migration InitialCreate”

ASP.NET样板开发框架ABP系列之ABP入门教程详解

会在Migrations文件夹下生成一个xxxx-InitialCreate.cs文件,内容如下:

public partial class InitialCreate : DbMigration{ public override void Up() {  CreateTable(   "dbo.StsPeople",   c => new    {     Id = c.Int(nullable: false, identity: true),     Name = c.String(),    })   .PrimaryKey(t => t.Id);     CreateTable(   "dbo.StsTasks",   c => new    {     Id = c.Long(nullable: false, identity: true),     AssignedPersonId = c.Int(),     Description = c.String(),     CreationTime = c.DateTime(nullable: false),     State = c.Byte(nullable: false),    })   .PrimaryKey(t => t.Id)   .ForeignKey("dbo.StsPeople", t => t.AssignedPersonId)   .Index(t => t.AssignedPersonId);    }   public override void Down() {  DropForeignKey("dbo.StsTasks", "AssignedPersonId", "dbo.StsPeople");  DropIndex("dbo.StsTasks", new[] { "AssignedPersonId" });  DropTable("dbo.StsTasks");  DropTable("dbo.StsPeople"); }}

登录后复制

然后继续在“程序包管理器控制台”执行“Update-Database”,会自动在数据库创建相应的数据表:

PM> Update-Database

登录后复制

数据库显示如下:

ASP.NET样板开发框架ABP系列之ABP入门教程详解

(以后修改了实体,可以再次执行Add-Migration和Update-Database,就能很轻松的让数据库结构与实体类的同步)

定义仓储接口

通过仓储模式,可以更好把业务代码与数据库操作代码更好的分离,可以针对不同的数据库有不同的实现类,而业务代码不需要修改。

定义仓储接口的代码写到Core项目中,因为仓储接口是领域层的一部分。

我们先定义Task的仓储接口:

public interface ITaskRepository : IRepository{

登录后复制

它继承自ABP框架中的IRepository泛型接口。

在IRepository中已经定义了常用的增删改查方法:

ASP.NET样板开发框架ABP系列之ABP入门教程详解

所以ITaskRepository默认就有了上面那些方法。可以再加上它独有的方法GetAllWithPeople(…)。

不需要为Person类创建一个仓储类,因为默认的方法已经够用了。ABP提供了一种注入通用仓储的方式,将在后面“创建应用服务”一节的TaskAppService类中看到。

实现仓储类

我们将在EntityFramework项目中实现上面定义的ITaskRepository仓储接口。

通过模板建立的项目已经定义了一个仓储基类:SimpleTaskSystemRepositoryBase(这是一种比较好的实践,因为以后可以在这个基类中添加通用的方法)。

public class TaskRepository : SimpleTaskSystemRepositoryBase, ITaskRepository{  public List GetAllWithPeople(int? assignedPersonId, TaskState? state)  {    //在仓储方法中,不用处理数据库连接、DbContext和数据事务,ABP框架会自动处理。          var query = GetAll(); //GetAll() 返回一个 IQueryable接口类型          //添加一些Where条件    if (assignedPersonId.HasValue)    {      query = query.Where(task => task.AssignedPerson.Id == assignedPersonId.Value);    }    if (state.HasValue)    {      query = query.Where(task => task.State == state);    }    return query      .OrderByDescending(task => task.CreationTime)      .Include(task => task.AssignedPerson)      .ToList();  }}

登录后复制

TaskRepository继承自SimpleTaskSystemRepositoryBase并且实现了上面定义的ITaskRepository接口。

创建应用服务(Application Services)

Application项目中定义应用服务。首先定义Task的应用服务层的接口:

public interface ITaskAppService : IApplicationService{  GetTasksOutput GetTasks(GetTasksInput input);  void UpdateTask(UpdateTaskInput input);  void CreateTask(CreateTaskInput input);}

登录后复制

ITaskAppService继承自IApplicationService,ABP自动为这个类提供一些功能特性(比如依赖注入和参数有效性验证)。

然后,我们写TaskAppService类来实现ITaskAppService接口:

public class TaskAppService : ApplicationService, ITaskAppService{  private readonly ITaskRepository _taskRepository;  private readonly IRepository _personRepository;      ///   /// 构造函数自动注入我们所需要的类或接口  ///   public TaskAppService(ITaskRepository taskRepository, IRepository personRepository)  {    _taskRepository = taskRepository;    _personRepository = personRepository;  }      public GetTasksOutput GetTasks(GetTasksInput input)  {    //调用Task仓储的特定方法GetAllWithPeople    var tasks = _taskRepository.GetAllWithPeople(input.AssignedPersonId, input.State);    //用AutoMapper自动将List转换成List    return new GetTasksOutput        {          Tasks = Mapper.Map>(tasks)        };  }      public void UpdateTask(UpdateTaskInput input)  {    //可以直接Logger,它在ApplicationService基类中定义的    Logger.Info("Updating a task for input: " + input);    //通过仓储基类的通用方法Get,获取指定Id的Task实体对象    var task = _taskRepository.Get(input.TaskId);    //修改task实体的属性值    if (input.State.HasValue)    {      task.State = input.State.Value;    }    if (input.AssignedPersonId.HasValue)    {      task.AssignedPerson = _personRepository.Load(input.AssignedPersonId.Value);    }    //我们都不需要调用Update方法    //因为应用服务层的方法默认开启了工作单元模式(Unit of Work)    //ABP框架会工作单元完成时自动保存对实体的所有更改,除非有异常抛出。有异常时会自动回滚,因为工作单元默认开启数据库事务。  }  public void CreateTask(CreateTaskInput input)  {    Logger.Info("Creating a task for input: " + input);    //通过输入参数,创建一个新的Task实体    var task = new Task { Description = input.Description };    if (input.AssignedPersonId.HasValue)    {      task.AssignedPersonId = input.AssignedPersonId.Value;    }    //调用仓储基类的Insert方法把实体保存到数据库中    _taskRepository.Insert(task);  }}

登录后复制

TaskAppService使用仓储进行数据库操作,它通往构造函数注入仓储对象的引用。

数据验证

如果应用服务(Application Service)方法的参数对象实现了IInputDto或IValidate接口,ABP会自动进行参数有效性验证。

CreateTask方法有一个CreateTaskInput参数,定义如下:

public class CreateTaskInput : IInputDto{  public int? AssignedPersonId { get; set; }  [Required]  public string Description { get; set; }}

登录后复制

Description属性通过注解指定它是必填项。也可以使用其他 Data Annotation 特性。

如果你想使用自定义验证,你可以实现ICustomValidate 接口:

public class UpdateTaskInput : IInputDto, ICustomValidate{  [Range(1, long.MaxValue)]  public long TaskId { get; set; }  public int? AssignedPersonId { get; set; }  public TaskState? State { get; set; }  public void AddValidationErrors(List results)  {    if (AssignedPersonId == null && State == null)    {      results.Add(new ValidationResult("AssignedPersonId和State不能同时为空!", new[] { "AssignedPersonId", "State" }));    }  }}

登录后复制

你可以在AddValidationErrors方法中写自定义验证的代码。

创建Web Api服务

ABP可以非常轻松地把Application Service的public方法发布成Web Api接口,可以供客户端通过ajax调用。

DynamicApiControllerBuilder  .ForAll(Assembly.GetAssembly(typeof (SimpleTaskSystemApplicationModule)), "tasksystem")  .Build();

登录后复制

SimpleTaskSystemApplicationModule这个程序集中所有继承了IApplicationService接口的类,都会自动创建相应的ApiController,其中的公开方法,就会转换成WebApi接口方法。

可以通过http://xxx/api/services/tasksystem/Task/GetTasks这样的路由地址进行调用。

通过上面的案例,大致介绍了领域层、基础设施层、应用服务层的用法。

现在,可以在ASP.NET MVC的Controller的Action方法中直接调用Application Service的方法了。

如果用SPA单页编程,可以直接在客户端通过ajax调用相应的Application Service的方法了(通过创建了动态Web Api)。

总结

以上就是ASP.NET样板开发框架ABP系列之ABP入门教程详解的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2493155.html

(0)
上一篇 2025年3月5日 01:26:19
下一篇 2025年2月23日 12:20:34

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • asp.net怎么使用js文件

    通常javascript代码可以与html标签一起直接放在前 端页面中,但如果js代码多的话一方面不利于维护,另一方面也对搜索引擎不友好,因为页面因此而变得臃肿。 所以一般有良好开发习惯的程序员都会把 javascript代码放到独立的js…

    2025年3月5日
    200
  • VSCode最适合哪种框架开发?

    VSCode是一款功能强大、灵活性高、易于扩展的开源代码编辑器,广受开发者青睐。它支持众多编程语言和框架,能够满足不同项目需求。但是,针对不同的框架,VSCode的优势可能有所不同。本文将讨论VSCode在不同框架开发中的适用性,并提供具体…

    2025年3月4日
    200
  • golang框架的行业标准

    go框架的行业标准包括:gin:轻量级且高性能的web框架。echo:快速、可扩展且灵活的web框架,具有restful api功能。gorm:用于go的现代orm(对象-关系映射)框架。 Go 框架的行业标准 在 Go 领域,选择合适的框…

    2025年3月4日
    200
  • golang框架开发经验总结

    golang 框架提升 web 应用开发:选择合适的框架,如 gin、echo 或 gorilla。遵循 mvc 模式,保持代码整洁,易于维护。利用依赖注入,简化测试和维护。通过实战案例,使用 gin 框架、gorm 和 wire 构建简单…

    2025年3月4日
    200
  • golang框架学习路线图

    go框架学习路线图:预备知识:go基础知识终端操作http和restful api入門階段:選擇框架(如gin)建立項目結構處理http路徑中級階段:使用模板引擎使用中間件執行錯誤處理高級階段:使用orm(如gorm)與資料庫互動處理並行處…

    2025年3月4日
    200
  • golang框架的社区支持怎么样?

    golang 框架拥有一个活跃的社区,提供广泛的支持:论坛和讨论组,如官方论坛和 stack overflow 上的 goland 标记。全面的官方文档和教程,可在 goland 网站和 github 存储库上找到。大量博客文章、在线课程和…

    2025年3月4日
    200
  • golang框架常见问题快速解答

    使用 golang 框架的常见问题快速解答:使用路由器: 利用 gorilla/mux 路由器映射 http 请求到处理程序。使用模板引擎: 通过 html/template 模板引擎动态创建 html 页面。处理错误: 使用 http.e…

    2025年3月4日
    200
  • golang框架开发流程的跨平台部署

    跨平台部署 go 框架应用程序流程:创建 docker 镜像:构建 dockerfile 和镜像。创建 docker compose 文件:定义容器和配置。设置 aws ecs:创建集群、任务定义和服务。实战案例:部署 go web 应用程…

    2025年3月4日
    200
  • golang框架使用中遇到的困惑和解答

    以下是在 go 框架开发中常见的困惑问题及其解答:数据库连接错误:使用 create 方法而不是 createdatabase 方法。null 字段错误:确保 null 字段可为空(字符串:string,时间:*time.time)。获取模…

    2025年3月4日
    200
  • golang框架学习者常见问题集锦

    常见问题一:如何创建 restful api?解决方案:使用 gorilla mux 库创建路由并处理 http 请求和响应。问题二:如何使用 orm 执行数据库操作?解决方案:使用 gorm 库建立与数据库的连接并执行 crud 操作。问…

    2025年3月4日
    200

发表回复

登录后才能评论