一、引言
上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中。本篇博文将使用AngularJS来打造一个简易的权限管理系统。下面不多说,直接进入主题。
二、整体架构设计介绍
首先看下整个项目的架构设计图:

从上图可以看出整个项目的一个整体结构,接下来,我来详细介绍了项目的整体架构:
采用Asp.net Web API来实现REST 服务。这样的实现方式,已达到后端服务的公用、分别部署和更好地扩展。Web层依赖应用服务接口,并且使用Castle Windsor实现依赖注入。
1、显示层(用户UI)
显示层采用了AngularJS来实现的SPA页面。所有的页面数据都是异步加载和局部刷新,这样的实现将会有更好的用户体验。
2、应用层(Application Service)
AngularJS通过Http服务去请求Web API来获得数据,而Web API的实现则是调用应用层来请求数据。
3、基础架构层
基础架构层包括仓储的实现和一些公用方法的实现。
仓储层的实现采用EF Code First的方式来实现的,并使用EF Migration的方式来创建数据库和更新数据库。
LH.Common层实现了一些公用的方法,如日志帮助类、表达式树扩展等类的实现。
4、领域层
领域层主要实现了该项目的所有领域模型,其中包括领域模型的实现和仓储接口的定义。
介绍完整体结构外,接下来将分别介绍该项目的后端服务实现和Web前端的实现。
三、后端服务实现
后端服务主要采用Asp.net Web API来实现后端服务,并且采用Castle Windsor来完成依赖注入。
这里拿权限管理中的用户管理来介绍Rest Web API服务的实现。
提供用户数据的REST服务的实现:
public class UserController : ApiController
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
[Route("api/user/GetUsers")]
public OutputBase GetUsers([FromUri]PageInput input)
{
return _userService.GetUsers(input);
}
[HttpGet]
[Route("api/user/UserInfo")]
public OutputBase GetUserInfo(int id)
{
return _userService.GetUser(id);
}
[HttpPost]
[Route("api/user/AddUser")]
public OutputBase CreateUser([FromBody] UserDto userDto)
{
return _userService.AddUser(userDto);
}
[HttpPost]
[Route("api/user/UpdateUser")]
public OutputBase UpdateUser([FromBody] UserDto userDto)
{
return _userService.UpdateUser(userDto);
}
[HttpPost]
[Route("api/user/UpdateRoles")]
public OutputBase UpdateRoles([FromBody] UserDto userDto)
{
return _userService.UpdateRoles(userDto);
}
[HttpPost]
[Route("api/user/DeleteUser/{id}")]
public OutputBase DeleteUser(int id)
{
return _userService.DeleteUser(id);
}
[HttpPost]
[Route("api/user/DeleteRole/{id}/{roleId}")]
public OutputBase DeleteRole(int id, int roleId)
{
return _userService.DeleteRole(id, roleId);
}
}
</div>
从上面代码实现可以看出,User REST 服务依赖与IUserService接口,并且也没有像传统的方式将所有的业务逻辑放在Web API实现中,而是将具体的一些业务实现封装到对应的应用层中,Rest API只负责调用对应的应用层中的服务。这样设计好处有:
1.REST 服务部依赖与应用层接口,使得职责分离,将应用层服务的实例化交给单独的依赖注入容器去完成,而REST服务只负责调用对应应用服务的方法来获取数据。采用依赖接口而不依赖与具体类的实现,使得类与类之间低耦合。
2.REST服务内不包括具体的业务逻辑实现。这样的设计可以使得服务更好地分离,如果你后期想用WCF来实现REST服务的,这样就不需要重复在WCF的REST服务类中重复写一篇Web API中的逻辑了,这时候完全可以调用应用服务的接口方法来实现WCF REST服务。所以将业务逻辑实现抽到应用服务层去实现,这样的设计将使得REST 服务职责更加单一,REST服务实现更容易扩展。
用户应用服务的实现:
public class UserService : BaseService, IUserService
{
private readonly IUserRepository _userRepository;
private readonly IUserRoleRepository _userRoleRepository;
public UserService(IUserRepository userRepository, IUserRoleRepository userRoleRepository)
{
_userRepository = userRepository;
_userRoleRepository = userRoleRepository;
}
public GetResults<UserDto> GetUsers(PageInput input)
{
var result = GetDefault<GetResults<UserDto>>();
var filterExp = BuildExpression(input);
var query = _userRepository.Find(filterExp, user => user.Id, SortOrder.Descending, input.Current, input.Size);
result.Total = _userRepository.Find(filterExp).Count();
result.Data = query.Select(user => new UserDto()
{
Id = user.Id,
CreateTime = user.CreationTime,
Email = user.Email,
State = user.State,
Name = user.Name,
RealName = user.RealName,
Password = "*******",
Roles = user.UserRoles.Take(4).Select(z => new BaseEntityDto()
{
Id = z.Role.Id,
Name = z.Role.RoleName
}).ToList(),
TotalRole = user.UserRoles.Count()
}).ToList();
return result;
}
public UpdateResult UpdateUser(UserDto user)
{
var result = GetDefault<UpdateResult>();
var existUser = _userRepository.FindSingle(u => u.Id == user.Id);
if (existUser == null)
{
result.Message = "USER_NOT_EXIST";
result.StateCode = 0x00303;
return result;
}
if (IsHasSameName(existUser.Name, existUser.Id))
{
result.Message = "USER_NAME_HAS_EXIST";
result.StateCode = 0x00302;
return result;
}
existUser.RealName = user.RealName;
existUser.Name = user.Name;
existUser.State = user.State;
existUser.Email = user.Email;
_userRepository.Update(existUser);
_userRepository.Commit();
result.IsSaved = true;
return result;
}
public CreateResult<int> AddUser(UserDto userDto)
{
var result = GetDefault<CreateResult<int>>();
if (IsHasSameName(userDto.Name, userDto.Id))
{
result.Message = "USER_NAME_HAS_EXIST";
result.StateCode = 0x00302;
return result;
}
var user = new User()
{
CreationTime = DateTime.Now,
Password = "",
Email = userDto.Email,
State = userDto.State,
RealName = userDto.RealName,
Name = userDto.Name
};
_userRepository.Add(user);
_userRepository.Commit();
result.Id = user.Id;
result.IsCreated = true;
return result;
}
public DeleteResult DeleteUser(int userId)
{
var result = GetDefault<DeleteResult>();
var user = _userRepository.FindSingle(x => x.Id == userId);
if (user != null)
{
_userRepository.Delete(user);
_userRepository.Commit();
}
result.IsDeleted = true;
return result;
}
public UpdateResult UpdatePwd(UserDto user)
{
var result = GetDefault<UpdateResult>();
var userEntity =_userRepository.FindSingle(x => x.Id == user.Id);
if (userEntity == null)
{
result.Message = string.Format("当前编辑的用户“{0}”已经不存在", user.Name);
return result;
}
userEntity.Password = user.Password;
_userRepository.Commit();
result.IsSaved = true;
return result;
}
public GetResult<UserDto> GetUser(int userId)
{
var result = GetDefault<GetResult<UserDto>>();
var model = _userRepository.FindSingle(x => x.Id ==

