@Aiti
2019-09-23T08:41:11.000000Z
字数 6731
阅读 369
MVC WebApi .Net XPO Swagger



1.web.config里面配置:
<appSettings><add key="XpoConnectionString" value="XpoProvider=MSSqlServer;data source=.;user id=sa;password=cx1234;initial catalog=TestWeb;Persist Security Info=true" /></appSettings>
2.封装XpoHelper方法用于获取session

3.控制器基类-ApiControllerBase类中获取session
public DevExpress.Xpo.Session session => XpoHelper.Session;

继承System.Web.Http.ApiController 的 ApiControllerBase类,被所有控制器继承,用于控制器接口类的通用处理,如文件的处理、session的设置.


2、Get方法因为返回的数据前端不能序列化,[导致报错]:ObjectContent`1”类型未能序列化内容类型“application/json; charset=utf-8”的响应正文。所以用到下面的视图类,设置返回的数据。


安装成功后,编写一个类(需继承AutoMapper中的基类 Profile)来存放实体类和视图类的映射关系
namespace TestWeb.App_Start{public class AutoMapperProfile: Profile{public AutoMapperProfile(){CreateMap<User, vUser>();}}}
public vUser Get(string loginname){var user = session.FindObject<User>(loginname);return AutoMapper.Mapper.Map<vUser>(user);}
在这里运行的话会提示AutoMapper没有初始化,Mapper not initialized.所以需要初始化AutoMapper;
需要在使用之前初始化,所以可以在Startup或者Global里面初始化;
Mapper.Initialize(x =>{x.CreateMap<User, vUser>();});
Mapper.Initialize(x => x.AddProfile<AutoMapperProfile>());
新增数据和编辑修改数据用同一个接口,所以首先要找到该类型的主键,判断其是否为null,如果为null,即新增数据;不为null,即编辑数据;新增时,主键不传或者传null,
/// <summary>/// 视图类转换XPO实体类/// </summary>public class ViewModelToXpoHelper{public static object GetKeyValue(BaseViewModel vModel, Type t, Session session){var keyFiled = session.GetClassInfo(t).KeyProperty.Name;var mc = new PropertyAccessor(vModel.GetType(), keyFiled);return mc.Get(vModel);}/// <summary>/// 视图类转换XPO实体类/// </summary>/// <typeparam name="T"></typeparam>/// <param name="vModel"></param>/// <param name="session"></param>/// <returns></returns>public static T ViewModelToXpo<T>(BaseViewModel vModel,Session session, XPBaseObject xpOrgin = null) where T: XPBaseObject{try{T xpoModel;if (xpOrgin == null){var keyValue = GetKeyValue(vModel, typeof(T), session);if (keyValue == null){//新建记录XPClassInfo classInfo = session.GetClassInfo(typeof(T));xpoModel = (T)classInfo.CreateNewObject(session);}else{//编辑记录xpoModel = session.GetObjectByKey<T>(keyValue);}}elsexpoModel = xpOrgin as T;//反射 填充xpoforeach (PropertyInfo pInfo in vModel.GetType().GetProperties()){try{var v = pInfo.GetValue(vModel);if (v != null){if (pInfo.PropertyType.IsSubclassOf(typeof(BaseViewModel))){Type t = xpoModel.ClassInfo.GetMember(pInfo.Name).MemberType;xpoModel.SetMemberValue(pInfo.Name, session.GetObjectByKey(t, GetKeyValue((BaseViewModel)v, t, session)));}else{xpoModel.SetMemberValue(pInfo.Name, v);}}}catch { }}return xpoModel;}catch(Exception e){}return null;}}
接口写法第一种(主键为默认Oid):
机构部门表,默认Oid为主键
public vDepartment Post([FromBody]vDepartment v){var o = ViewModelToXpoHelper.ViewModelToXpo<Department>(v, session);o.Save();return AutoMapper.Mapper.Map<vDepartment>(o);}
接口写法第二种(自定义主键):
用户表,自定义主键为登录名LoginName,主键不存在未null的情况
public vUser Post([FromBody]vUser v){var o = ViewModelToXpoHelper.ViewModelToXpo<User>(v, session,v.IsNew? new User(session):null);return AutoMapper.Mapper.Map<vUser>(o);}
public IHttpActionResult Delete(string loginname){var user = session.GetObjectByKey<User>(loginname);user.Delete();return Ok("删除成功!");}

请求带分页的列表:
1. 首先接收的对象需要包括:请求页码、请求页码大小(每页显示数量),请求条件集合;
2. 根据接收的对象中的请求条件对数据进行过滤等到实体类的List集合;
3. 需要AutoMapper将实体类的List集合进行映射到视图发送给前端,前端接收到的对象包括:list集合,当前页码、页码大小、总页数、总元素个数
4. 所以也要有对应的一个类对象包含前端接收的这些数据才能通过AutoMapper映射给前端(可以理解为User和vUser通过Mapper映射的,vUser里有的属性,User里面肯定有;反之不一定)
5. 这里可能涉及LINQ 和 Lambda 表达式 以及 DevExpress的CriteriaOperator过滤对象;需要提前学习。
看代码:
1、接收请求的类
2、数据处理后传给前端的视图类
3、需要通过Mapper映射给前端的类,这里包括了前端视图类所需要的属性,还有写了构造函数和方法,new一个对象时,通过构造函数和方给这些前端视图类需要的对应的属性赋值。
namespace TestWeb.Common.Engine{/// <summary>/// 分页/// </summary>/// <typeparam name="T"></typeparam>public class PageingHelper<T>{/// <summary>/// 分页编号/// </summary>public int CurrentPage { get; set; }/// <summary>/// 分页大小/// </summary>public int PageSize { get; private set; }private int? _totalCount;/// <summary>/// 元素总共数目/// </summary>public int TotalCount{get{if (_totalCount == null) _totalCount = Query.Count();return (int)_totalCount;}}/// <summary>/// 页数/// </summary>public int PageCount{get{return TotalCount == 0 ? 0 : (int)Math.Ceiling((decimal)TotalCount / PageSize);}}private IQueryable<T> Query { get; set; }public List<T> List { get; private set; }/// <summary>/// 构造函数/// </summary>/// <param name="list">链表</param>/// <param name="intPageIndex">编号</param>/// <param name="intPageSize">大小</param>public PageingHelper(IQueryable<T> list, int intPageIndex, int intPageSize){CurrentPage = intPageIndex;PageSize = intPageSize;Query = list;GetPagedList();}/// <summary>/// 转为为分页/// </summary>/// <param name="list">链表</param>public void GetPagedList(){if (CurrentPage > PageCount) CurrentPage = PageCount;if (CurrentPage < 1) CurrentPage = 1;int intStart = (CurrentPage - 1) * PageSize;List = Query.Skip(intStart).Take(PageSize).ToList();}}}
4、将已经过滤的List集合通过Mapper映射返回给前端

首先选择项目注释信息的生成位置

1、给Web的Help Api添加注释

2、给swagger添加注释信息

1.密码加密
选择MD5加密方式加密,
[Persistent("Password"),Size(20)]private string _password;[DisplayName("密码")]public string Password{get { return _password; }set { _password = ConvertHelper.MD5(value); }}
加密帮助类
using System;using System.Security.Cryptography;using System.Text;public class ConvertHelper{/// <summary>/// MD加密/// </summary>/// <param name="value">源值</param>/// <param name="salt">盐值</param>/// <returns></returns>public static string MD5(string value,string salt="Aiti"){byte[] v = Encoding.Default.GetBytes(salt + value.ToString());MD5 md = new MD5CryptoServiceProvider();byte[] mv = md.ComputeHash(v);return BitConverter.ToString(mv).Replace("-", "");}}
1、继承 System.Web.HttpApplication 的 FormsAuthenticationHttpApplication类,被Global继承,用于登录时信息验证
public class FormsAuthenticationHttpApplication : System.Web.HttpApplication{//身份验证protected void Application_AuthenticateRequest(object sender, EventArgs e){try{if (HttpContext.Current.User != null){if (HttpContext.Current.User.Identity.IsAuthenticated){if (HttpContext.Current.User.Identity is FormsIdentity){FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;FormsAuthenticationTicket ticket = id.Ticket;string userData = ticket.UserData;string[] roles = userData.Split(',');HttpContext.Current.User = new GenericPrincipal(id, roles);}}}}catch{Response.Write(Context.User.Identity.AuthenticationType);Response.End();}}}
在上面写了身份验证还需要去web.config中设置验证方式为Forms表单验证
<system.web><authentication mode="Forms"><forms loginUrl="/home/login" enableCrossAppRedirects="true" protection="All" slidingExpiration="true" timeout="60" /></authentication></system.web>
这样登录页登录过后,再次进入页面就不需要再进行登录,会记录登录状态。
前后端分离时,前端也要控制cookie,切换浏览器要跳出重新登录。
或者web.config中添加sessionState的mode模式
<system.web><sessionState mode="InProc" timeout="20" />