水平有限,不足之处烦请指点。
最近做移动WMS项目,遇到了一些问题,解决了一些问题,绕过了一些问题,是时候整理一下了。本文讲的是项目中涉及到一个数据通信的问题。以前在上家公司用的是直接是引入WebService,感觉这个不太好,每次变化后都要重新引用。新系统听取了其他人的建议,决定用ASP.NET网站来做。
目标定下了,就要补充细节。
1.本项目是纯粹的数据交互接口,没有页面,不对外展示,决定全部使用一般处理程序来做。
2.接口的一定要简洁明了,其它的数据判断、异常、耗时记录、数据接收和返回都封装好。后续的人只需要把逻辑代码向里面填充即可。
3.考虑到大部分是字符串类的数据,决定使用json作为数据格式。并约定好请求返回数据格式。
4.开工吧。
上张图
首先,是用到的类。
// 主类
public class ApiModel<T1, T2>
{
public HttpContext Context { get; set; }
public Stopwatch Watch { get; set; }
public WMS_ApiLogInfo ApiLogInfo { get; set; }// 统计类
public RequestModel<T1> RequestModel { get; set; }
public ResponseModel<T2> ResponseModel { get; set; }
public string Msg { get; set; }
}
// 请求数据
public class RequestModel<T>
{
/// <summary>
/// 用户名:工号
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string PassWord { get; set; }
/// <summary>
/// 设备号
/// </summary>
public string DeviceNo { get; set; }
/// <summary>
/// 设备IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 请求时间
/// </summary>
public DateTime RequesTime
{
get { return DateTime.Now; }
}
/// <summary>
/// 请求数据
/// </summary>
public T RequestData { get; set; }
}
// 返回数据
public class ResponseModel<T>
{
public bool IsSucc { get; set; }
public string ErrMsg { get; set; }
public T ReturnModel { get; set; }
}
[Serializable]
public class WMS_ApiLogInfo
{
public string Guid { get; set; }
public string ApiName { get; set; }
public string UserName { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public string IP { get; set; }
public string MacAddress { get; set; }
public string RequestData { get; set; }
public string ResponseData { get; set; }
// 耗时
public string UseTime { get; set; }
}
具体的写法,一般处理程序封装
/// <summary>
/// $codebehindclassname$ 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public abstract class Base<T1, T2> : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
ApiModel<T1, T2> apiModel = new ApiModel<T1, T2>
{
Context = context,
Watch = new Stopwatch(),
ApiLogInfo = new WMS_ApiLogInfo()
{
StartTime = DateTime.Now,
ApiName = context.Request.CurrentExecutionFilePath,
Guid = Guid.NewGuid().ToString(),
},
ResponseModel = new ResponseModel<T2>() {IsSucc = false}
};
try
{
if (!Check(apiModel)) return;
Do(apiModel);
}
catch (Exception ex)
{
apiModel.ResponseModel.ErrMsg = ex.Message;
ResponseMsg(apiModel);
}
}
public bool IsReusable
{
get { return false; }
}
// 合法数据验证
public virtual bool Check(ApiModel<T1, T2> apiModel)
{
apiModel.Watch.Start();
apiModel.Context.Response.ContentType = "text/plain";
if (apiModel.Context.Request.HttpMethod != "POST")
{
apiModel.Msg = "请使用POST方法请求!";
ResponseMsg(apiModel);
return false;
}
string requestStr = string.Empty;
using (Stream resStream = HttpContext.Current.Request.InputStream)
{
using (StreamReader sr = new StreamReader(resStream, Encoding.Default))
{
requestStr = sr.ReadToEnd();
}
}
apiModel.ApiLogInfo.RequestData = requestStr;
apiModel.RequestModel = JsonConvertHelper.Json2Entity<RequestModel<T1>>(requestStr);
if (apiModel.RequestModel == null)
{
apiModel.Msg = "没有POST数据!";
ResponseMsg(apiModel);
return false;
}
apiModel.ApiLogInfo.MacAddress = apiModel.RequestModel.DeviceNo;
apiModel.ApiLogInfo.UserName = apiModel.RequestModel.UserName;
apiModel.ApiLogInfo.IP = apiModel.RequestModel.IP;
// 设备检查
// 员工检查
return true;
}
// 子类重载,然后构建逻辑
public virtual void Do(ApiModel<T1, T2> apiModel)
{
}
/// <summary>
/// 创建接口日志
/// </summary>
/// <param name="apiModel"></param>
private void CreateApiLog(ApiModel<T1, T2> apiModel)
{
if (apiModel.Watch == null || apiModel.ApiLogInfo == null) return;
apiModel.ApiLogInfo.EndTime = DateTime.Now;
apiModel.Watch.Stop();
apiModel.ApiLogInfo.UseTime = Method.GetUseTime(apiModel.Watch);
// 创建接口调用日志
}
/// <summary>
/// 输出结果
/// </summary>
/// <param name="apiModel"></param>
public void ResponseMsg(ApiModel<T1, T2> apiModel)
{
string result = string.Empty;
apiModel.ResponseModel.ErrMsg = apiModel.Msg;
result = JsonConvertHelper.Obj2Json(apiModel.ResponseModel);
apiModel.Context.Response.Write(result);
apiModel.ApiLogInfo.ResponseData = result;
CreateApiLog(apiModel);
}
// 邮件方法、短信方法等等,供子类使用
}
子类的写法,两个示例
public class GetJHDHList : Base<string, List<string>>
{
public override void Do(ApiModel<string, List<string>> apiModel)
{
// 逻辑代码
List<JHDInfo> list = new List<JHDInfo>();
// 没有数据
if (list.Count == 0)
{
apiModel.Msg = "没有查到可拣单号列表!";
}
else
{
// 有数据
apiModel.ResponseModel.ReturnModel =
list.Select(o => o.JHDH).ToList();
apiModel.ResponseModel.IsSucc = true;
}
ResponseMsg(apiModel);
}
}
public class LoginIn : Base<string, XT_YGInfo>
{
public override void Do(ApiModel<string, XT_YGInfo> apiModel)
{
// 逻辑代码,检查用户是否能登录
// 失败,提示
var flag=false;
if (flag)
{
apiModel.Msg = "密码错误!";
ResponseMsg(apiModel);
return;
}
// 成功,返回PDA权限、仓库、用户名等等信息。
apiModel.ResponseModel.IsSucc = true;
apiModel.ResponseModel.ReturnModel = info;
ResponseMsg(apiModel);
}
}
公共方法
// 使用的json.net做类型转换
public class JsonConvertHelper
{
public static string Obj2Json(object obj)
{
try
{
return JsonConvert.SerializeObject(obj);
}
catch (Exception ex)
{
throw new Exception("JsonConvertHelper.Obj2Json():" + ex.Message);
}
}
public static T Json2Entity<T>(string jsonstr)
{
try
{
return JsonConvert.DeserializeObject<T>(jsonstr);
}
catch (Exception ex)
{
throw new Exception("JsonConvertHelper.Json2Entity():" + ex.Message);
}
}
}
public class Method
{
public static string GetUseTime(Stopwatch watch)
{
if (watch == null)
return null;
return watch.Elapsed.Days + ":" + watch.Elapsed.Hours + ":" + watch.Elapsed.Minutes + ":" +
watch.Elapsed.Seconds + ":" + watch.Elapsed.Milliseconds;
}
}
ok,完成了,上面只写了UI层的调用关系,可以和其他层接驳。不过,PDA端的代码及逻辑没有贴出来。
主要是涉及到太多的项目内调用。我具体的做法是建一个api的项目,里面写的都是调用具体的方法,处理http请求和返回数据的一段代码封装一下。
然后在UI层创建api请求数据,并处理返回数据。
做这个项目最大的收获就是大部分架构都是我构思设计的,可能有些微bug、可能功能较弱,但我收获的更多。对项目的理解更深,对代码的堆砌更有心得。
-----------
每天进步一点点