下载自:https://github.com/aspnetboilerplate/module-zero
打开D:\ABP\module-zero-master\sample里的ModuleZeroSampleProject.sln项目文件,马上还原程序包,试图update-database,报错,说没这个命令。
网上搜了半天,才看到解决方法:
输入set-executionpolicy remotesigned
再输入:
PM> Import-Module D:\ABP\module-zero-master\sample\packages\EntityFramework.6.1.3\tools\EntityFramework.psd1
PM> update-database
终于搞定。
(奇怪的是,重新解压,直接编译,让VS自动还原程序包,就不会出现上面的问题,直接update-database通过)
还有就是别手痒,去更新程序包,我下载的项目里还使用jquery-2.1.3.min.js,一更新就被换成jquery-2.1.4.min.js,但是BundleConfig类里还是2.1.3,没有改2.1.4啊…………
启动ModuleZeroSampleProject.Web项目,使用admin/123qwe登录没有问题。但是如果无输入、乱输入,则没有任何错误提示。
参考http://qasample.aspnetboilerplate.com/示例网站,分明是有错误提示的嘛:

原来还得改Web.config:
<customErrors mode="On" />
一个典型的ABP项目:
先看Core项目下的实体:
用户:
User继承的是AbpUser<Tenant, User>
UserManager继承的是AbpUserManager<Tenant, Role, User>
UserStore继承的是AbpUserStore<Tenant, Role, User>
这几个类实际上并无增加内容,仅仅是直接继承而已。需要注意的是User所继承的AbpUser<Tenant, User>使用了子类User作为TUser
角色:
Role继承的是AbpRole<Tenant, User>
RoleStore继承的是AbpRoleStore<Tenant, Role, User>
RoleManager继承的是AbpRoleManager<Tenant, Role, User>
PermissionChecker继承的是PermissionChecker<Tenant, Role, User>
同样,这些子类都没有增加内容。
租户:
Tenant继承的是AbpTenant<Tenant, User>
问题和回答:
Question继承了CreationAuditedEntity<int, User>,表明这个类要求包含创建者信息,后面可以看到需要使用到它的CreatorUser属性。
在数据表Questions里能够发现:
这个字段并没有在Question类里出现,要在CreationAuditedEntity里找:
因为问题和回答是一对多关系,所以有属性:
public virtual ICollection<Answer> Answers { get; set; }
Answer也继承了CreationAuditedEntity<int, User>
注意到有属性IsAccepted
领域服务:QuestionDomainService,继承了DomainService类
这个服务就是放“接受答案”方法的地方:
就是如果已有接受的答案,则找出来,设置为非接受,然后设置传入的答案为已接受。
注意在这个类已经使用了IRepository<Answer>
再看ModuleZeroSampleProject.EntityFramework项目下的ModuleZeroSampleProjectDbContext类
继承的是AbpZeroDbContext<Tenant, Role, User>
声明了:
public virtual IDbSet<Question> Questions { get; set; }
public virtual IDbSet<Answer> Answers { get; set; }
但是查看数据库,数据表可不止这两个。
再看ModuleZeroSampleProject.Application项目:
ModuleZeroSampleProjectAuthorizationProvider类,继承AuthorizationProvider,声明了几个权限:
创建问题、删除问题、删除答案、回答问题。
设置类MySettingProvider,继承SettingProvider,设置了一页显示10条问题。
IUserAppService声明了GetUsers方法,也就是用户列表。
IQuestionAppService声明了
GetQuestions获得所有问题
CreateQuestion创建问题
GetQuestion获取一个问题
VoteUp加1投票
VoteDown减1投票
SubmitAnswer回答问题
AcceptAnswer接受答案
再看实现:QuestionAppService类
GetQuestions方法中,读取了MySettingProvider里的配置:
input.MaxResultCount = SettingManager.GetSettingValue<int>(MySettingProvider.QuestionsDefaultPageSize);
获取问题列表,需要注意输入的参数为GetQuestionsInput对象,该对象实现了IPagedResultRequest、ISortedResultRequest
看表达式
需要知道,Question类继承了CreationAuditedEntity<int, User>,因而具有CreateUser属性。
这里使用了EF里扩展的Include方法,要求根据外键CreatorUserID来加载创建者
PageBy方法是ABP扩展的一个分页方法。
另外要注意的是automapping:
[AutoMapFrom(typeof(Question))]
public class QuestionDto : CreationAuditedEntityDto
QuestionDto 类只有CreatorUserName属性,而没有CreatorUserID属性,但是还能映射:
Items = questions.MapTo<List<QuestionDto>>()
CreateQuestion方法:
可以看到CreateQuestion方法前,加了[AbpAuthorize("CanCreateQuestions")] 特性,对权限的验证非常便捷。
异步插入数据的写法:
GetQuestion方法:
跨表查询好狠:
var question =
_questionRepository
.GetAll()
.Include(q => q.CreatorUser)
.Include(q => q.Answers)
.Include("Answers.CreatorUser")
.FirstOrDefault(q => q.Id == input.Id);
SubmitAnswer方法:
使用了 _unitOfWorkManager.Current.SaveChanges();
AcceptAnswer方法:
直接调用了领域服务:_questionDomainService.AcceptAnswer(answer)
再看Tests项目对上面服务方法的测试,首先进行注入:
声明一个继承于AbpIntegratedTestBase的类SampleProjectTestBase,其构造函数
具体的测试类如UserAppService_Tests,需要继承SampleProjectTestBase
重新生成,就可以运行测试了:
Web项目,AccountController类,注意到使用了UserManager、AuthenticationManager
通过HttpContext.GetOwinContext().Authentication获取AuthenticationManager,使用了Owin
UserManager是通过AccountController的构造函数传入的,前者的父类有实现ITransientDependency,所以这里会被自动注入。
使用:
var loginResult = await _userManager.LoginAsync(
loginModel.UsernameOrEmailAddress,
loginModel.Password,
loginModel.TenancyName
);
LoginAsync方法:
public virtual Task<AbpUserManager<TTenant, TRole, TUser>.AbpLoginResult> LoginAsync(string userNameOrEmailAddress, string plainPassword, string tenancyName = null)
这方法需要去zero的源码里研究
AuthenticationManager可直接使用其SignIn、SignOut方法:
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = loginModel.RememberMe }, loginResult.Identity);
HomeController加了 [AbpMvcAuthorize]特性。
Startup类可以看到配置,[assembly: OwinStartup(typeof(Startup))]
在Configuration方法里
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
详情参考文章
- ABP 极简入门教程(一)
本示例不讲概念,只讲怎么用,概念性的内容没有比官方文档更清楚的了,我也正在学习,可能理解的地方有不对的欢迎一起交流,但需要您了解以下内容才能看明白 asp.net core Entity Framew ...
- abp zero sample
测试运行地址:http://ghy.demo.aspnetzero.com 账号:admin 密码:123456 需要源码,请加QQ:858-048-581 一.用户管理 二.日志记录 1.先编译成 ...
- ABP文档 - 本地化
文档目录 本节内容: 简介 应用语言 本地化源 XML文件 注册XML本地化源 JSOn文件 注册JSON本地化源 资源文件 自定义源 获取一个本地文本 在服务端 在MVc控制器里 在MVC视图里 在 ...
- ABP文档 - 异常处理
文档目录 本节内容: 简介 启用错误处理 非AJAX请求 显示异常 UserFriendlyException Error 模型 AJAX 请求 异常事件 简介 这个文档针对Asp.net Mvc和W ...
- ABP(现代ASP.NET样板开发框架)系列之8、ABP日志管理
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之8.ABP日志管理 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...
- ABP(现代ASP.NET样板开发框架)系列之23、ABP展现层——异常处理
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之23.ABP展现层——异常处理 ABP是“ASP.NET Boilerplate Project (ASP.NET ...
- ABP框架 - 日志
文档目录 本节内容: 服务端 获取Logger(记录器) Logger的基类 配置 Abp.Castle.Log4Net 包 客户端 服务端 ABP使用Castle Windsor的日志记录工具,它可 ...
- ABP框架 - 功能管理
文档目录 本节内容: 简介 关于 IFeatureValueStore 功能类型 Boolean 功能 Value 功能 定义功能 基本功能属性 其它功能属性 功能层次 检查功能 使用Requires ...
- Abp集成Swagger的最佳实践
1.在项目中添加nuget包 Abp.Web.Api.SwaggerTool 2.在项目Abp模块的DependsOn添加AbpWebApiSwaggerToolModule Run It,启动项目, ...
随机推荐
- make自动生成依赖文件的两种形式
最近编译源文件发现当修改头文件后,make并不会自动把包含此头文件的所有源文件重新编译,而每次都是需要把对应的中间文件清除才能重新编译,非常的麻烦.因此需要make自动对源文件所依赖的头文件进行管理, ...
- Redis部分数据结构方法小结
package com.practice.util; import java.util.HashMap; import java.util.List; import java.util.Map; im ...
- 有关项目上潜在需要的移动端GIS系统源码整理,待后续更新
GPS Tools For Android 前言: GPS数据在做GIS开发时的一份宝贵的数据,在不侵犯他人隐私的情况下通过互联网的模式收集GPS是成本最为低廉的一种模式. 背景: 现在公司在做一个项 ...
- 理解Python装饰器
装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权 ...
- 手把手教你接口自动化测试 – SoapUI & Groovy
手把手教你接口自动化测试 – SoapUI & Groovy http://www.cnblogs.com/wade-xu/p/4236295.html 关键词:SoapUI接口测试,接口自动 ...
- JAVA设计模式之迭代子模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述迭代子(Iterator)模式的: 迭代子模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不 ...
- Android UI 绘制过程浅析(一)LayoutInflater简介
前言 这篇blog是我在阅读过csdn大牛郭霖的<带你一步步深入了解View>一系列文章后,亲身实践并做出的小结.作为有志向的前端开发工程师,怎么可以不搞懂View绘制的基本原理——简直就 ...
- JSTL+MyEclipse8.5+Tomcat配置
使用JSTL的时候需要配置,即导入stdandard.jar和jstl.jar包,并在web.xml下对jstl进行配置.下面是使用步骤: 1. 解压jakarta-taglibs-standard- ...
- HDU5900
http://acm.hdu.edu.cn/showproblem.php?pid=5900 就是给出两行数字,每行有若干的数,如果相邻的两个数字的最大公约数不是1 的话拟具可以把这两数删除,并且把第 ...
- Android BaseAdapter的使用
数据适配器有很多种,今天在这里记录一下最通用是适配器BaseAdapter. 首先说一下什么是适配器,这里我从网上找到一幅图片 由上图我们不难看出,所谓的适配器,就是数据与视图之间的桥梁.由它把数据绑 ...