1,DbFirst创建EF数据模型(Models,Dto。通过Dto我们实现了表现层与Model之间的解耦。)
2,创建和实现数据访问层IDAL、业务逻辑层IBLL。
①创建IDAL层:
IBaseService:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Eims.IDAL
{
public interface IBaseService<T> : IDisposable where T : class
{
Task<int> InsertAsync(T model, bool saved = true);
Task<int> UpdateAsync(T model, bool saved = true);
Task<int> DeleteAsync(int id, bool saved = true);
Task<int> Save();
IQueryable<T> GetAll();
}
}
IStaffService:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Eims.Models;
namespace Eims.IDAL
{
public interface IStaffService : IBaseService<Staff>
{
}
}
②创建DAL层,他们实现IDAL
BaseService:
using Eims.IDAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Eims.Models;
using System.Data.Entity;
namespace Eims.DAL
{
public class BaseService<T> : IBaseService<T>, IDisposable where T : class, new()
{
private readonly EimsContext _db;
public BaseService(EimsContext db)
{
_db = db;
}
public async Task<int> InsertAsync(T model, bool saved = true)
{
_db.Set<T>().Add(model);
if (saved) return await Save();
else return -1;//-2,-1,0,>0
}
public async Task<int> DeleteAsync(int id, bool saved = true)
{
_db.Configuration.ValidateOnSaveEnabled = false;
var t=_db.Set<T>().Find(id);
_db.Entry(t).State = EntityState.Deleted;
if (saved) return await Save();
else return -1;
}
public async Task<int> UpdateAsync(T model, bool saved = true)
{
_db.Configuration.ValidateOnSaveEnabled = false;
_db.Entry(model).State = EntityState.Modified;
if (saved) return await Save();
else return -1;
}
public async Task<int> Save()
{
try
{
int i = await _db.SaveChangesAsync();
_db.Configuration.ValidateOnSaveEnabled = true;
return i;
}
catch { return -2; }
}
public IQueryable<T> GetAll()
{
return _db.Set<T>().AsNoTracking();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
}
StaffService:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Eims.IDAL;
using Eims.Models;
namespace Eims.DAL
{
public class StaffService : BaseService<Staff>, IStaffService
{
public StaffService()
: base(new EimsContext())
{
}
}
}
③创建IBLL层
IBaseManager
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Eims.Dto;
namespace Eims.IBLL
{
public interface IBaseManager<T>
{
Task<List<T>> _getPage(T model, int pageSize = 10, int pageIndex = 0);
Task<List<T>> _getAll();
Task<int> _add(T model);
Task<int> _edit(T model);
Task<int> _del(int id);
}
}
IStaffManager:
using Eims.Dto;
using System.Threading.Tasks;
namespace Eims.IBLL
{
public interface IStaffManager : IBaseManager<StaffDto>
{
Task<AccountDto> _login(int id, string password);
}
}
④创建BLL层,他们实现IBLL
StaffManager:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Eims.IBLL;
using Eims.Dto;
using Eims.IDAL;
using Unity;
using System.Data.Entity;
namespace Eims.BLL
{
public class StaffManager : IStaffManager
{
[Dependency]
public IStaffService staffService { get; set; }
public async Task<int> _add(StaffDto staffDto)
{
return await staffService.InsertAsync(new Models.Staff()
{
Address=staffDto.Address,
Birthday=staffDto.Birthday,
EducationLevel=staffDto.EducationLevel,
Email=staffDto.Email,
GraduatedSchool=staffDto.GraduatedSchool,
HealthStatus=staffDto.HealthStatus,
Hometown=staffDto.Hometown,
Id=staffDto.Id,
IDcard=staffDto.IDcard,
MaritalStatus=staffDto.MaritalStatus,
Name=staffDto.Name,
Password=staffDto.Password,
Phone=staffDto.Phone,
RoleId=staffDto.RoleId,
PoliticalStatus=staffDto.PoliticalStatus,
Sex=staffDto.Sex,
WorkingState=staffDto.WorkingState
});
}
public async Task<int> _del(int id)
{
return await staffService.DeleteAsync(id);
}
public async Task<int> _edit(StaffDto staffDto)
{
return await staffService.UpdateAsync(new Models.Staff()
{
Address = staffDto.Address,
Birthday = staffDto.Birthday,
EducationLevel = staffDto.EducationLevel,
Email = staffDto.Email,
GraduatedSchool = staffDto.GraduatedSchool,
HealthStatus = staffDto.HealthStatus,
Hometown = staffDto.Hometown,
Id = staffDto.Id,
IDcard = staffDto.IDcard,
MaritalStatus = staffDto.MaritalStatus,
Name = staffDto.Name,
Password = staffDto.Password,
Phone = staffDto.Phone,
RoleId = staffDto.RoleId,
PoliticalStatus = staffDto.PoliticalStatus,
Sex = staffDto.Sex,
WorkingState = staffDto.WorkingState
});
}
public async Task<List<StaffDto>> _getAll()
{
return await staffService.GetAll().Select(m=> new StaffDto()
{
Address = m.Address,
Birthday = m.Birthday,
EducationLevel = m.EducationLevel,
Email = m.Email,
GraduatedSchool = m.GraduatedSchool,
HealthStatus = m.HealthStatus,
Hometown = m.Hometown,
Id = m.Id,
IDcard = m.IDcard,
MaritalStatus = m.MaritalStatus,
Name = m.Name,
Password = m.Password,
Phone = m.Phone,
RoleId = m.RoleId,
PoliticalStatus = m.PoliticalStatus,
Sex = m.Sex,
WorkingState = m.WorkingState
}).ToListAsync();
}
public async Task<List<StaffDto>> _getPage(StaffDto model, int pageSize, int pageIndex)
{
return await staffService.GetAll().Where(m => m.Id == model.Id || m.Name == model.Name || m.IDcard == model.IDcard).OrderBy(m => m.Id).Skip(pageSize * pageIndex).Take(pageSize).Select(m => new StaffDto()
{
Address = m.Address,
Birthday = m.Birthday,
EducationLevel = m.EducationLevel,
Email = m.Email,
GraduatedSchool = m.GraduatedSchool,
HealthStatus = m.HealthStatus,
Hometown = m.Hometown,
Id = m.Id,
IDcard = m.IDcard,
MaritalStatus = m.MaritalStatus,
Name = m.Name,
Password = m.Password,
Phone = m.Phone,
RoleId = m.RoleId,
PoliticalStatus = m.PoliticalStatus,
Sex = m.Sex,
WorkingState = m.WorkingState
}).ToListAsync();
}
public async Task<AccountDto> Login(int id, string password)
{
var staff = staffService.GetAll().FirstOrDefault(m => m.Id == id && m.Password == password);
if (staff == null) return null;
return new AccountDto()
{
Id=staff.Id,
RoleId=staff.RoleId,
};
}
}
}
3,创建 依赖关系 容器。这是为了在多个项目中重复使用,比如WebMVC和WebApi。
using Eims.BLL;
using Eims.DAL;
using Eims.IBLL;
using Eims.IDAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity;
namespace Eims.Core
{
public partial class RegisterTypes
{
/// <summary>
/// Registers the type mappings with the Unity container.
/// </summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>
/// There is no need to register concrete types such as controllers or
/// API controllers (unless you want to change the defaults), as Unity
/// allows resolving a concrete type even if it was not previously
/// registered.
/// </remarks>
public static void Partial(IUnityContainer container)
{
container.RegisterType<IAttendanceManager, AttendanceManager>();
container.RegisterType<IAttendanceService, AttendanceService>();
container.RegisterType<IArticleManager, ArticleManager>();
container.RegisterType<IArticleService, ArticleService>();
container.RegisterType<IStaffManager, StaffManager>();
container.RegisterType<IStaffService, StaffService>();
container.RegisterType<ISuggestManager, SuggestManager>();
container.RegisterType<ISuggestService, SuggestService>();
container.RegisterType<IWageManager, WageManager>();
container.RegisterType<IWageService, WageService>();
}
}
}
4,创建项目Apps.WebApi
5,jwt解密和加密工具类。
token:
-
header (base64后的)
-
payload (base64后的)
-
signature:它由header、payload、secret加密生成。不知道secret就无法解密。
验证过程:用户登陆后服务器向客户端签发token,客户端请求服务器携带token,服务器进行通过解密token进行身份校验。
服务器解密后可将解密信息(例如:权限Id)存入上下文供Controller使用。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using JWT.Exceptions;
using Newtonsoft.Json;
namespace Eims.WebApi.Core
{
public class JwtTools
{
public static string Key { get; set; } = "wangzhenyang";
public static string Encode(Dictionary<string, object> payload, string key = null)
{
if (string.IsNullOrEmpty(key)) key = Key;
payload.Add("timeout", DateTime.Now.AddDays(1));
IJsonSerializer jsonSerializer = new JsonNetSerializer();//json序列化
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加密编码器
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//算法
IJwtEncoder jwtEncoder = new JwtEncoder(algorithm, jsonSerializer, urlEncoder);
return jwtEncoder.Encode(payload, key);
}
public static Dictionary<string, object> Decode(string code, string key = null)
{
if (string.IsNullOrEmpty(key)) key = Key;
try
{
IJsonSerializer jsonSerializer = new JsonNetSerializer();//json序列化
IDateTimeProvider provider = new UtcDateTimeProvider();//日期提供者
IJwtValidator jwtValidator = new JwtValidator(jsonSerializer, provider);//验证器
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加密编码器
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//算法
IJwtDecoder jwtDecoder = new JwtDecoder(jsonSerializer, jwtValidator, urlEncoder, algorithm);
var json = jwtDecoder.Decode(code, key, true);
var result = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
if ((DateTime)result["timeout"] < DateTime.Now)
throw new Exception("jwtstring已经过期,必须重新登陆");
result.Remove("timeout");
return result;
}
catch (TokenExpiredException) { throw; }
}
}
}
6,在Api项目内,创建过滤器类MainAuthAttribute,他实现接口Attribute, IAuthorizationFilter。
注意:①在控制器上添加注释[MainAuth]后,会在运行该控制器时调用Filter
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Filters;
using Eims.WebApi.Core;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http;
using Eims.WebApi.Models.Auth;
namespace Eims.WebApi.Filter
{
public class MainAuthAttribute : Attribute, IAuthorizationFilter
{
public bool RoleValidation { get; set; } = false;//是否开启权限验证
public bool AllowMultiple => throw new NotImplementedException();
public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
//获取request->headers->token
IEnumerable<string> headers;
if (actionContext.Request.Headers.TryGetValues("token", out headers))
{
//解密token为键值对
Dictionary<string, object> keyValues = JwtTools.Decode(headers.First());
int id = Convert.ToInt32(keyValues["Id"].ToString());
int roleId = Convert.ToInt32(keyValues["RoleId"].ToString());
//将解密内容存入user->identiey
(actionContext.ControllerContext.Controller as ApiController).User = new ApplicationUser(id, roleId);
//验证类别
if (RoleValidation == false || roleId == 0)
{
return await continuation();
}
}
return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
}
}
7,WebApi全局的依赖注入
8,可以在项目中创建BaseController通用类
9,测试类TestController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Unity;
using Eims.Dto;
using Eims.IBLL;
using System.Threading.Tasks;
using System.Web.Http.Cors;
using Eims.WebApi.Models;
using Eims.WebApi.Filter;
using Eims.WebApi.Models.Auth;
using Eims.WebApi.Core;
/*
* 测试api
*/
namespace Eims.WebApi.Controllers
{
[RoutePrefix(prefix: "api/test")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class TestController : ApiController
{
[Dependency]
public IAttendanceManager attendanceManager { get; set; }
[Dependency]
public IArticleManager articleManager { get; set; }
[Dependency]
public IWageManager wageManager { get; set; }
[Dependency]
public ISuggestManager suggestManager { get; set; }
[Dependency]
public IStaffManager staffManager { get; set; }
[Route(""), HttpGet]
public async Task<IHttpActionResult> Test()
{
/*//_add
string str = "@@@@@@@@@@";
string result = "";
result += await attendanceManager._add(new AttendanceDto()
{
Id = 1,
Remarks = str
});
result += await articleManager._add(new ArticleDto()
{
Title = str
});
result += await wageManager._add(new WageDto()
{
Remark = str
});
result += await suggestManager._add(new SuggestDto()
{
Content = str
});
result += await staffManager._add(new StaffDto()
{
Id = 5555,
Name = str
});
return Ok(result); */
/*//_getPage
return Ok(await attendanceManager._getPage(new AttendanceDto()
{
Name = "name"
}));*/
/*//_del
return Ok(await staffManager._del(5555));*/
//_edit
return Ok(await suggestManager._edit(new SuggestDto()
{
Id = 2,
Content="工资太高,1亿就可🙆",
SuggestTime=DateTime.Now,
Title = "工资问题",
StaffId=0
}));
}
[HttpPost, Route("login")]
public async Task<IHttpActionResult> login(LoginViewModel model)
{
if (ModelState.IsValid)
{
AccountDto user = await staffManager.Login(model.Id, model.Password);
if (user == null)
return Ok(new ResponseData()
{
Code = 0,
ErrorMessage = "密码错误或账号不存在"
});
return Ok(new ResponseData()
{
Data = JwtTools.Encode(new Dictionary<string, object>()
{
{ "Id",user.Id },
{ "RoleId",user.RoleId }
})
});
}
else
{
return Ok(new ResponseData() { Code = 0, ErrorMessage = "账号密码输入有误" });
}
}
[MainAuth(RoleValidation = true)]
[HttpGet, Route("getAll")]
public IHttpActionResult getAll()
{
UserIdentity my = ((UserIdentity)User.Identity);
if (my.RoleId != 0)
return Ok(new ResponseData()
{
Code = 0,
ErrorMessage = "你没有管理员权限"
});
return Ok(my);
}
[HttpPost]
public Dictionary<string, Object> parm(AccountDto model, string str, int i)
{
return new Dictionary<string, object>()
{
{ "2",model }
};
}
}
}