@Aiti
2019-09-23T08:41:11.000000Z
字数 6731
阅读 311
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);
}
}
else
xpoModel = xpOrgin as T;
//反射 填充xpo
foreach (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" />