使用Angular2及WebApi开发SPA类型的企业应用 - Part 2- 添加新角色

使用Angular2及RESTful WebApi开发SPA类型的企业应用 - Part 2 添加新角色
作者:techcoaching,翻译:飘落寒冰
原文 有道
注:第一次翻译文章,有错译之处还请多多包涵,欢迎指出以便改进。

在本文中,我们将学习如何创建和编辑角色
从Github上下载源码

该系列的全部文章

  1. 概览
  2. 添加新角色
  3. 项目结构
  4. 多语言
  5. 依赖注入和控制反转-为什么和为什么不?
  6. RESTful & WebApi
  7. 应用生命周期管理
  8. 应用构建与部署

简介

本部分,我们将通过一系列步骤来学习如何使用代码来实现添加角色页面:
image

分析页面

我习惯在实现页面之前先做分析,能帮我们发现:
- 列出完成该页面的所有需要实现的步骤。
- 找出缺少的信息,然后立即寻求帮助
- 思考从客户端到服务器端的逻辑流程,从UI到数据访问,这有助于我们更好的编码。我的很多同事习惯先写代码,然后Debug。当有错误发生时,它令你不得不修改代码去维持系统运转,这样做很可能打破系统的逻辑流程,而且修改的代码往往不太符合该程序开发的结构与规范。这些将来可能会引发新的潜在的问题并且代码难以维护。
分析完页面之后,我们找出了以下需要完成的事情:

客户端
  • 为“添加角色”页面注册路由(angular2组件)
  • 创建组件文件(UI的html文件,逻辑处理的ts文件,组件视图模型的ts文件)
  • 实现角色管理组件的UI
  • 实现角色管理的逻辑(包含请求服务器及获取数据)
  • 实现页面的请求(请求通过调用REST api来获取授权列表)
API
  • 在RolesController中增加一个方法处理创建角色的请求,Role作为参数
  • 在Role service 和 Role repository 中各增加一个创建Role的方法

在客户端实现

在本节,目录为客户端所在目录

  1. 为“添加角色”页面注册路由(angular2组件)
    到”/app/modules/secutiry/_share/config”中更新 addRoutes 方法如下:
import {IModule, Module, MenuItem} from "../../../../common/models/layout";
import {Roles} from "../../role/roles";
import {AddRole} from "../../role/addRole";
import {AuthenticationMode} from "../../../../common/enum";
import route from "./route";
let module: IModule = createModule();
export default module;
function createModule() {
    let module = new Module("app/modules/secutiry", "secutiry");
    module.menus.push(
        new MenuItem(
            "Security", route.role.roles.name, "fa fa-user-md",
            new MenuItem("Roles", route.role.roles.name, ""),
        )
    );
    module.addRoutes([
        { path: route.role.roles.path, name: route.role.roles.name, component: Roles, 
          data: { authentication: AuthenticationMode.Require }, useAsDefault: true },
        { path: route.role.addRole.path, name: route.role.addRole.name, component: AddRole, 
          data: { authentication: AuthenticationMode.Require } }
    ]);
    return module;
}

route.ts 内容:

let route = {
    role: {
        roles: { name: "Roles", path: "/roles" },
        addRole: { name: "Add Role", path: "/addRole" }
    }
};
export default route;
  1. 创建组件文件(UI的html文件,逻辑处理的ts文件,组件视图模型的ts文件)
    image

  2. 实现角色管理组件的UI

<page>
    <page-header>
        {{i18n.security.addOrUpdateRole.title}}
    </page-header>
    <page-content>
        <form-default>
            <form-text-input [placeHolderText]=i18n.security.addOrUpdateRole.inputName 
              [labelText]=i18n.security.addOrUpdateRole.name

                [validation]="['security.addOrUpdateRole.validation.nameIsRequire',
                 'security.addOrUpdateRole.validation.keyAlreadyExisted']"
                [(model)]=model.name>
            </form-text-input>
            <form-textarea [placeHolderText]=i18n.security.addOrUpdateRole.inputDesc 
             [labelText]=i18n.security.addOrUpdateRole.desc [(model)]=model.description>
            </form-textarea>

            <form-permission-select [(values)]=model.permissions 
             [placeHolderText]=i18n.security.addOrUpdateRole.inputPermissions 
             [labelText]=i18n.security.addOrUpdateRole.permission

                [(model)]=model.permissions>
            </form-permission-select>

            <form-footer>
                <button id="save" 
                (click)="onSaveClicked($event)" type="button" 
                 class="btn btn-primary">{{i18n.common.form.save}}</button>
                <button id="cancel" 
                (click)="onCancelClicked($event)" type="button" 
                 class="btn btn-default">{{i18n.common.form.cancel}}</button>
            </form-footer>
        </form-default>
    </page-content>
</page>

浏览器输出:
image

该文件中:
- 我们用的不是标准HTML创建UI和Form,我们用了一些指令来完成这个工作,例如form, form-textarea, ······
- 本页的结构:
- page-header: 包含页首内容
- page-content: 包含页面主要内容

  1. 实现角色管理的逻辑
import {BasePage} from "../../../common/models/ui";
import {Router, RouteParams} from "angular2/router";
import {Component} from "angular2/core";
import {AddRoleModel} from "./addRoleModel";
import {Page, SelectPermission, Form, FormTextInput, FormFooter, 
        FormTextArea, FormPermissionSelect} from "../../../common/directive";
import {ValidationDirective} from "../../../common/directive";
import roleService from "../_share/services/roleService";
import {FormMode} from "../../../common/enum";
import route from "../_share/config/route";
@Component({
    templateUrl: "app/modules/security/role/addRole.html",
    directives: [Page, Form, FormTextInput, FormFooter, FormTextArea, FormPermissionSelect]
})
export class AddRole extends BasePage {
    public model: AddRoleModel = new AddRoleModel();
    private router: Router;
    constructor(router: Router, routeParams: RouteParams) {
        super();
        let self: AddRole = this;
        self.router = router;
    }
    public onSaveClicked(event: any): void {
        let self: AddRole = this;
        roleService.create(this.model).then(function () {
            self.router.navigate([route.role.roles.name]);
        });
    }
    public onCancelClicked(event: any): void {
        let self: AddRole = this;
        self.router.navigate([route.role.roles.name]);
    }
}

该文件中:
- 通过routeParams.get(“id”)获得选中角色的id
- 通过调用router.navigate切换页面

  1. 实现页面的请求(请求通过调用REST api来获取授权列表)
import configHelper from "../../../../common/helpers/configHelper";
import {Promise} from "../../../../common/models/promise";
let roleServices = {
    getRoles: getRoles,
    create: create
};
export default roleServices;
function getRoles(): Promise {
    let connector = window.ioc.resolve("IConnector");
    let url = String.format("{0}roles", configHelper.getAppConfig().api.baseUrl);
    return connector.get(url);
}

function create(role: any): Promise {
    let connector = window.ioc.resolve("IConnector");
    let url = String.format("{0}roles", configHelper.getAppConfig().api.baseUrl);
    return connector.post(url, role);
}

实现API

  1. 在RolesController中增加一个方法处理创建角色的请求,Role作为参数
using App.Common.DI;
using App.Common.Http;
using App.Common.Validation;
using App.Service.Security;
using System;
using System.Collections.Generic;
using System.Web.Http;

namespace App.Api.Features.Security
{
    [RoutePrefix("api/roles")]
    public class RolesController : ApiController
    {
        [HttpGet]
        [Route("")]
        public IResponseData<IList<RoleListItemSummary>> GetRoles()
        {
            IResponseData<IList<RoleListItemSummary>> response = 
                             new ResponseData<IList<RoleListItemSummary>>();
            try
            {
                IRoleService roleService = IoC.Container.Resolve<IRoleService>();
                IList<RoleListItemSummary> roles=roleService.GetRoles();
                response.SetData(roles);
            }
            catch (ValidationException ex)
            {
                response.SetErrors(ex.Errors);
                response.SetStatus(System.Net.HttpStatusCode.PreconditionFailed);
            }
            return response;
        }

        [HttpPost]
        [Route("")]
        public IResponseData<CreateRoleResponse> CreateRole(CreateRoleRequest request)
        {
            IResponseData<CreateRoleResponse> response = new ResponseData<CreateRoleResponse>();
            try
            {
                IRoleService roleService = IoC.Container.Resolve<IRoleService>();
                CreateRoleResponse role = roleService.Create(request);
                response.SetData(role);
            }
            catch (ValidationException ex)
            {
                response.SetErrors(ex.Errors);
                response.SetStatus(System.Net.HttpStatusCode.PreconditionFailed);
            }
            return response;
        }
    }
}
  1. 在IRoleService 和 RoleService 中各增加一个创建Role的方法
    • IRoleService.cs
namespace App.Service.Security
{
    public interface IRoleService
    {
        System.Collections.Generic.IList<RoleListItemSummary> GetRoles();
        CreateRoleResponse Create(CreateRoleRequest request);
    }
}
  • RoleService.cs
using System.Collections.Generic;
using App.Service.Security;
using App.Common.DI;
using App.Repository.Secutiry;
using App.Entity.Security;
using App.Common;
namespace App.Service.Impl.Security
{
    public class RoleService : IRoleService
    {
        public CreateRoleResponse Create(CreateRoleRequest request)
        {
            ValidateCreateRequest(request);
            using (App.Common.Data.IUnitOfWork uow = 
            new App.Common.Data.UnitOfWork(new App.Context.AppDbContext(IOMode.Write)))
            {
                IRoleRepository roleRepository = 
                IoC.Container.Resolve<IRoleRepository>(uow);
                IPermissionRepository permissionRepo = 
                IoC.Container.Resolve<IPermissionRepository>(uow);
                IList<Permission> permissions = 
                permissionRepo.GetPermissions(request.Permissions);
                Role role = new Role(request.Name, request.Description, permissions);
                roleRepository.Add(role);
                uow.Commit();
            }
            return new CreateRoleResponse();
        }
        private void ValidateCreateRequest(CreateRoleRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.Name))
            {
                throw new App.Common.Validation.ValidationException
                ("security.addOrUpdateRole.validation.nameIsRequire");
            }
        }
        public IList<RoleListItemSummary> GetRoles()
        {
            IRoleRepository repository = IoC.Container.Resolve<IRoleRepository>();
            return repository.GetItems<RoleListItemSummary>();
        }
    }
}

Role service:
- 通过调用Role repository 中的Create方法创建角色。
- 需要特别指出的是,我们使用了UnitOfWork(单元工作模式),来避免一些意料之外的更改被保存到数据库中。
- Exception “security.addOrUpdateRole.validation.nameIsRequire”, 会在客户端以当前的语言,以tooltip的方式展示到组件内。本示例中我们只将错误的Key返回到客户端,客户端将根据其的语言显示相应的内容。

  1. IRoleRepository 和 RoleRepository 用来创建Role。
    我们不需要对repository继承的方法做任何修改。
namespace App.Repository.Secutiry
{
    public interface IRoleRepository: App.Common.Data.IBaseContentRepository<Role>
    {
    }
}

using App.Common.Data.MSSQL;
using App.Entity.Security;
using App.Repository.Secutiry;

namespace App.Repository.Impl.Security
{
    public class RoleRepository: BaseContentRepository<Role>, IRoleRepository
    {
        public RoleRepository() : base(new App.Context.AppDbContext(App.Common.IOMode.Read))
        {
        }

        public RoleRepository(IUnitOfWork uow) : base(uow.Context as IMSSQLDbContext)
        {
        }
    }
}

总结

到目前为止,我们已经能够创建一个新的角色。

授权

本文,以及所包含的源码,文件遵循CPOL协议

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值