返回《Module Zero学习目录》



这里需要抱歉的是,这里使用的博客园的Markdown语法,代码显示不是很好看,没有行号,而且外面还有一个双层框,大家将就着看吧!至于这个双层框,我也不知道怎么回事,不过博客园官方给的例子是没双层框的,如果你知道如何去掉这个框,也麻烦回复一下吧!


使用模板创建(自动方式)##

使用ABP和Module-Zero开始一个新的项目最简单的方式通过ABP官网的模板页面创建一个解决方案的模板。看下一篇博客《启动模板》

手动安装

如果你之前已经创建了应用,且以后安装module-zero,那么你可以按下面的步骤来做。

在这篇博客中,我假设你的解决方案有了以下这些项目:

AbpZeroSample.Core

AbpZeroSample.Application

AbpZeroSample.EntityFramework

AbpZeroSample.Web

AbpZeroSample.WebApi

核心(领域)层

将Abp.Zero nuget包安装到.Core项目中,然后在core module类(本例是AbpZeroSampleCoreModule类)中给AbpZeroCoreModule添加DependsOn特性,如下所示:

[DependsOn(typeof(AbpZeroCoreModule))]
public class AbpZeroSampleCoreModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}

领域类(实体)

Module-zero提供了抽象类User, Role和Tenant,因此我们应该像下面那样实现它们:

public class User : AbpUser<Tenant, User>
{ } public class Role : AbpRole<Tenant, User>
{ } public class Tenant : AbpTenant<Tenant, User>
{ }

你可以在这里添加自定义的属性。通过这种方式,我们可以根据自己的需求扩展User, Role和Tenant基类。

管理者(领域服务)

因为管理者和存储基类都是抽象的,所以我们应该实现它们。

让我们从User存储和User管理者开始:

public class UserStore : AbpUserStore<Tenant, Role, User>
{
public UserStore(
IRepository<User, long> userRepository,
IRepository<UserLogin, long> userLoginRepository,
IRepository<UserRole, long> userRoleRepository,
IRepository<Role> roleRepository,
IRepository<UserPermissionSetting, long> userPermissionSettingRepository,
IUnitOfWorkManager unitOfWorkManager,
ICacheManager cacheManager)
: base(
userRepository,
userLoginRepository,
userRoleRepository,
roleRepository,
userPermissionSettingRepository,
unitOfWorkManager,
cacheManager)
{
}
} public class UserManager : AbpUserManager<Tenant, Role, User>
{
public UserManager(
UserStore userStore,
RoleManager roleManager,
IRepository<Tenant> tenantRepository,
IMultiTenancyConfig multiTenancyConfig,
IPermissionManager permissionManager,
IUnitOfWorkManager unitOfWorkManager,
ISettingManager settingManager,
IUserManagementConfig userManagementConfig,
IIocResolver iocResolver,
ICacheManager cacheManager
)
: base(
userStore,
roleManager,
tenantRepository,
multiTenancyConfig,
permissionManager,
unitOfWorkManager,
settingManager,
userManagementConfig,
iocResolver,
cacheManager)
{
}
}

不要担心依赖列表,这可能会在下个版本中改变。如果需要的话,只要排列好构造函数就可以了。这对于RoleStore和RoleManager是相似的。

public class RoleStore : AbpRoleStore<Tenant, Role, User>
{
public RoleStore(
IRepository<Role> roleRepository,
IRepository<UserRole, long> userRoleRepository,
IRepository<RolePermissionSetting, long> rolePermissionSettingRepository,
ICacheManager cacheManager)
: base(
roleRepository,
userRoleRepository,
rolePermissionSettingRepository,
cacheManager)
{
}
} public class RoleManager : AbpRoleManager<Tenant, Role, User>
{
public RoleManager(
RoleStore store,
IPermissionManager permissionManager,
IRoleManagementConfig roleManagementConfig,
ICacheManager cacheManager)
: base(
store,
permissionManager,
roleManagementConfig,
cacheManager)
{
}
}

这里是租户管理者(tenant manager),没有租户存储类。

public class TenantManager : AbpTenantManager<Tenant, Role, User>
{
public TenantManager(EditionManager editionManager) :
base(editionManager)
{
}
}

最后是特征值存储和版本管理者。


public class FeatureValueStore : AbpFeatureValueStore<Tenant, Role, User>
{
public FeatureValueStore(TenantManager tenantManager)
: base(tenantManager)
{
}
} public class EditionManager : AbpEditionManager
{
}

权限管理者

为了使授权系统生效,我们应该实现权限管理者:

public class PermissionChecker : PermissionChecker<Tenant, Role, User>
{
public PermissionChecker(UserManager userManager)
: base(userManager)
{ }
}

基础设施层

EntityFramework

如果你选择了EntityFramework,那么我们应该给它配置module-zero。将Abp.Zero.EntityFramework nuget包安装到.EntityFramework项目中,然后在module文件(本例中是AbpZeroSampleDataModule)中,将AbpEntityFrameworkModule依赖改为AbpZeroEntityFrameworkModule,如下所示:

[DependsOn(typeof(AbpZeroEntityFrameworkModule), typeof(AbpZeroSampleCoreModule))]
public class AbpZeroSampleDataModule : AbpModule
{
//...
}

DbContext

在DbContext类中,将基类从AbpDbContext改为AbpZeroDbContext,如下所示:

public class AbpZeroSampleDbContext : AbpZeroDbContext<Tenant, Role, User>
{
//...
}

这样,来自module-zero的实体基类就加到了你的数据库上下文中。

数据库迁移(Database Migration)

因为我们的数据库上下文已经改变了,所以,现在我们应该创建数据库迁移。打开包管理器控制台,然后输入以下命令:

Add-Migration "AbpZero_Installed"

当然,你可以选择一个不同的迁移名字。在包管理器控制台管理器中不要忘了选择默认的项目为.EntityFramework项目。执行完此命令后,项目中会生成一个新的迁移文件。检查一下,如果需要的话,你可以做出修改。然后输入下面的命令来更新数据库模式:

Update-Database

你可以查看EF Code-First文档,获取更多信息。

初始化数据(Initial Data)

如果你检查了你的数据库,那么你会发现数据表已经创建了,但是表都是空的。你可以通过EF的种子来初始化数据。你可以使用这么一个类作为初始化数据生成器:

public class DefaultTenantRoleAndUserBuilder
{
private readonly AbpZeroSampleDbContext _context; public DefaultTenantRoleAndUserBuilder(AbpZeroSampleDbContext context)
{
_context = context;
} public void Build()
{
CreateUserAndRoles();
} private void CreateUserAndRoles()
{
//Admin role for tenancy owner var adminRoleForTenancyOwner = _context.Roles.FirstOrDefault(r => r.TenantId == null && r.Name == "Admin");
if (adminRoleForTenancyOwner == null)
{
adminRoleForTenancyOwner = _context.Roles.Add(new Role {Name = "Admin", DisplayName = "Admin"});
_context.SaveChanges();
} //Admin user for tenancy owner var adminUserForTenancyOwner = _context.Users.FirstOrDefault(u => u.TenantId == null && u.UserName == "admin");
if (adminUserForTenancyOwner == null)
{
adminUserForTenancyOwner = _context.Users.Add(
new User
{
TenantId = null,
UserName = "admin",
Name = "System",
Surname = "Administrator",
EmailAddress = "admin@aspnetboilerplate.com",
IsEmailConfirmed = true,
Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==" //123qwe
}); _context.SaveChanges(); _context.UserRoles.Add(new UserRole(adminUserForTenancyOwner.Id, adminRoleForTenancyOwner.Id)); _context.SaveChanges();
} //Default tenant var defaultTenant = _context.Tenants.FirstOrDefault(t => t.TenancyName == "Default");
if (defaultTenant == null)
{
defaultTenant = _context.Tenants.Add(new Tenant {TenancyName = "Default", Name = "Default"});
_context.SaveChanges();
} //Admin role for 'Default' tenant var adminRoleForDefaultTenant = _context.Roles.FirstOrDefault(r => r.TenantId == defaultTenant.Id && r.Name == "Admin");
if (adminRoleForDefaultTenant == null)
{
adminRoleForDefaultTenant = _context.Roles.Add(new Role { TenantId = defaultTenant.Id, Name = "Admin", DisplayName = "Admin" });
_context.SaveChanges();
} //Admin for 'Default' tenant var adminUserForDefaultTenant = _context.Users.FirstOrDefault(u => u.TenantId == defaultTenant.Id && u.UserName == "admin");
if (adminUserForDefaultTenant == null)
{
adminUserForDefaultTenant = _context.Users.Add(
new User
{
TenantId = defaultTenant.Id,
UserName = "admin",
Name = "System",
Surname = "Administrator",
EmailAddress = "admin@aspnetboilerplate.com",
IsEmailConfirmed = true,
Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==" //123qwe
});
_context.SaveChanges(); _context.UserRoles.Add(new UserRole(adminUserForDefaultTenant.Id, adminRoleForDefaultTenant.Id));
_context.SaveChanges();
}
}
}

这个类会创建默认的租户,角色和用户。我们可以在EF的Configuration类中将种子数据初始化到数据库:

internal sealed class Configuration : DbMigrationsConfiguration<AbpZeroSample.EntityFramework.AbpZeroSampleDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "AbpZeroSample";
} protected override void Seed(AbpZeroSample.EntityFramework.AbpZeroSampleDbContext context)
{
context.DisableAllFilters();
new DefaultTenantRoleAndUserBuilder(context).Build();
}
}

这里,我们禁用了数据过滤器(为的是我们可以自由地操作数据库)并使用了初始化数据生成器类。

展示层

Nuget包

将下面的nuget包添加到.Web项目中:

  • Abp.Zero.EntityFramework(这个也会添加Abp.Zero和所有依赖)
  • Microsoft.AspNet.Identity.Owin
  • Microsoft.Owin.Host.SystemWeb

Owin Startup类

添加一个Owin Startup类如下:

using AbpZeroSample.Web;
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin; [assembly: OwinStartup(typeof(Startup))] namespace AbpZeroSample.Web
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
}); // Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
}
}
}

Account Controller

我们可以创建一个用于登录/注销的控制器,如下:

public class AccountController : AbpZeroSampleControllerBase
{
private readonly UserManager _userManager; private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
} public AccountController(UserManager userManager)
{
_userManager = userManager;
} public ActionResult Login(string returnUrl = "")
{
if (string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl = Request.ApplicationPath;
} ViewBag.ReturnUrl = returnUrl; return View();
} [HttpPost]
public async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "")
{
if (!ModelState.IsValid)
{
throw new UserFriendlyException("Your form is invalid!");
} var loginResult = await _userManager.LoginAsync(
loginModel.UsernameOrEmailAddress,
loginModel.Password,
loginModel.TenancyName
); switch (loginResult.Result)
{
case AbpLoginResultType.Success:
break;
case AbpLoginResultType.InvalidUserNameOrEmailAddress:
case AbpLoginResultType.InvalidPassword:
throw new UserFriendlyException("Invalid user name or password!");
case AbpLoginResultType.InvalidTenancyName:
throw new UserFriendlyException("No tenant with name: " + loginModel.TenancyName);
case AbpLoginResultType.TenantIsNotActive:
throw new UserFriendlyException("Tenant is not active: " + loginModel.TenancyName);
case AbpLoginResultType.UserIsNotActive:
throw new UserFriendlyException("User is not active: " + loginModel.UsernameOrEmailAddress);
case AbpLoginResultType.UserEmailIsNotConfirmed:
throw new UserFriendlyException("Your email address is not confirmed!");
default: //Can not fall to default for now. But other result types can be added in the future and we may forget to handle it
throw new UserFriendlyException("Unknown problem with login: " + loginResult.Result);
} AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = loginModel.RememberMe }, loginResult.Identity); if (string.IsNullOrWhiteSpace(returnUrl))
{
returnUrl = Request.ApplicationPath;
} return Json(new MvcAjaxResponse { TargetUrl = returnUrl });
} public ActionResult Logout()
{
AuthenticationManager.SignOut();
return RedirectToAction("Login");
}
}

还有一个简单的LoginViewModel类:


public class LoginViewModel
{ public string TenancyName { get; set; } [Required]
public string UsernameOrEmailAddress { get; set; } [Required]
public string Password { get; set; } public bool RememberMe { get; set; }
}

Login视图

为了可以使用AccountController,我们应该创建一个login页面。创建一个login表单取决于你。只需要经由具有合适参数的AJAX调用AccountController的Login方法就可以了。

应用安全

现在,我们可以在HomeController上添加一个AbpAuthorize特性就可以确保只有已经验证的用户可以进入该页面:

[AbpMvcAuthorize]
public class HomeController : AbpZeroSampleControllerBase
{
public ActionResult Index()
{
return View("~/App/Main/views/layout/layout.cshtml"); //Layout of the angular application.
}
}

Module Zero安装的更多相关文章

  1. linux下安装VMware出错:Gtk-Message: Failed to load module "canberra-gtk-module"解决方法

    最近又有兴趣在linux下搭建个虚拟机,于是去找了个VMWorkstation,安装的过程中报了两个错误 Gtk-Message: Failed to load module "pk-gtk ...

  2. python windows package/module 安装

    方法一: cmd中运行pip install xx 注意:1.pip添加至环境变量 2.系统自带这些安装模块 运行pip freeze > requirements.txt 可以在require ...

  3. Linux CPAN Perl 模块安装

    当我们想使用某些Perl模块的时候,很可能会遇到当前系统不存在这个模块的情况,这时我们可以通过使用CPAN来对相应的模块进行获取,下面就介绍一下CPAN的使用方法.首先,我们可以用perl -e 'u ...

  4. windows下安装KeystoneJS

    安装参考: http://keystonejs.com/zh/getting-started/ http://jsnoder.com/kjs/quickstart 安装前提条件: 安装 Node.JS ...

  5. Node.js 的module 系统

    相较于原生的JavaScript,不同的JavaScript文件之间很难共享变量.有鉴于此,Node.js在JavaScript的基础上进行了扩充,引入了require,exports,module三 ...

  6. perl模块安装

    转自: http://www.cnblogs.com/itech/archive/2009/08/10/1542832.html http://www.mike.org.cn/blog/index.p ...

  7. Ansible安装部署以及常用模块详解

    一.  Ansible 介绍Ansible是一个配置管理系统configuration management system, python 语言是运维人员必须会的语言, ansible 是一个基于py ...

  8. 如何在Window下安装node\npm\cnpm,并安装vue.js,创建项目

    1.安装node.js node.js的官方地址为:https://nodejs.org/en/download/. 根据windows版本后,选择要下载的安装包,下载完毕,按照windows一般应用 ...

  9. vue安装搭建

    title: vue安装搭建 date: 2018-04-21 14:00:03 tags: [vue] --- 安装 首先安装nodejs 直接官网下载最新版本http://nodejs.cn/do ...

随机推荐

  1. 进击的Python【第十七章】:jQuery的基本应用

    进击的Python[第十七章]:jQuery的基本应用

  2. .NET平台常用的框架整理

    基于.NET平台常用的框架整理 DotNet | 2016-03-31 17:13 (点击上方蓝字,可快速关注我们) 来源:天使不哭 链接:http://www.cnblogs.com/hgmyz/p ...

  3. 老生长谈的$.extend()方法

    jq的extend()是jq插件扩展很重要的部分,到这里证明是可以自己在jq的基础上,分为两种方法去扩展或开发,为jq本身添加一个方法,可以理解成扩展静态方法和自定义方法. 今天有看到一篇帖子,对这部 ...

  4. Ubuntu14.04 64位机上安装cuda8.0 cudnn5.0操作步骤 - 网络资源是无限的

    查看Ubuntu14.04 64位上显卡信息,执行: lspci | grep -i vga lspci -v -s 01:00.0 nvidia-smi 第一条此命令可以显示一些显卡的相关信息:如果 ...

  5. WinForm开发笔记

    Button Button默认不产生DoubleClick事件 (MSDN说明:https://msdn.microsoft.com/zh-cn/library/system.windows.form ...

  6. 前馈网络求导概论(一)·Softmax篇

    Softmax是啥? Hopfield网络的能量观点 1982年的Hopfiled网络首次将统计物理学的能量观点引入到神经网络中, 将神经网络的全局最小值求解,近似认为是求解热力学系统的能量最低点(最 ...

  7. UVALive-4839 HDU-3686 Traffic Real Time Query System 题解

    题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...

  8. [8.3] Magic Index

    A magic index in an array A[0...n-1] is defined to be an index such that A[i] = i. Given a sorted ar ...

  9. 图解修改mysql的默认数据库存放目录

    按照下图三步完成:

  10. Hive文件存储格式

    hive文件存储格式 1.textfile textfile为默认格式   存储方式:行存储   磁盘开销大 数据解析开销大   压缩的text文件 hive无法进行合并和拆分 2.sequencef ...