开源组件websocket-sharp中基于webapi的httpserver使用体验
一、背景
因为需要做金蝶ERP的二次开发,金蝶ERP的开放性真是不错,但是二次开发金蝶一般使用引用BOS.dll的方式,这个dll对newtonsoft.json.dll这个库是强引用,必须要用4.0版本,而asp.net mvc的webapi client对newtonsoft.json.dll的最低版本是6.0.这样就不能用熟悉的webapi client开发了。金蝶ERP据说支持无dll引用方式,标准的webapi方式,但官方支持有限,网上的文档也有限且参考意义不大。所以最后把目光聚集在自建简单httpserver上,最好是用.net 4作为运行时。在此感谢“C#基于websocket-sharp实现简易httpserver(封装)”作者的分享,了解到这个开源组件。
二、定制和修改
- 1、修改“注入控制器到IOC容器”的方法适应现有项目的解决方案程序集划分
- 2、修改“响应HttpPost请求”时方法参数解析和传递方式,增加了“FromBoby”自定义属性来标记参数是个数据传输对象。
- 3、扩展了返回值类型,增加了HtmlResult和ImageResult等类型
代码:
1)、修改“注入控制器到IOC容器”的方法
/// <summary> /// 注入控制器到IOC容器 /// </summary> /// <param name="builder"></param> public void InitController(ContainerBuilder builder) { Assembly asb = Assembly.Load("Business.Controller"); if (asb != null) { var typesToRegister = asb.GetTypes() .Where(type => !string.IsNullOrEmpty(type.Namespace)) .Where(type => type.BaseType == typeof(ApiController) || type.BaseType.Name.Equals("K3ErpBaseController")); if (typesToRegister.Count() > 0) { foreach (var item1 in typesToRegister) { builder.RegisterType(item1).PropertiesAutowired(); foreach (var item2 in item1.GetMethods()) { IExceptionFilter _exceptionFilter = null; foreach (var item3 in item2.GetCustomAttributes(true)) { Attribute temp = (Attribute)item3; Type type = temp.GetType().GetInterface(typeof(IExceptionFilter).Name); if (typeof(IExceptionFilter) == type) { _exceptionFilter = item3 as IExceptionFilter; } } MAction mAction = new MAction() { RequestRawUrl = @"/" + item1.Name.Replace("Controller", "") + @"/" + item2.Name, Action = item2, TypeName = item1.GetType().Name, ControllerType = item1, ParameterInfo = item2.GetParameters(), ExceptionFilter = _exceptionFilter }; dict.Add(mAction.RequestRawUrl, mAction); } } } } container = builder.Build(); }
2)、修改“响应HttpPost请求”时方法参数解析和传递方式,增加了“FromBoby”自定义属性;增加了HtmlResult和ImageResult等类型
/// <summary> /// 响应HttpPost请求 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Httpsv_OnPost(object sender, HttpRequestEventArgs e) { MAction requestAction = new MAction(); string content = string.Empty; try { byte[] binaryData = new byte[e.Request.ContentLength64]; content = Encoding.UTF8.GetString(GetBinaryData(e, binaryData)); string action_name = string.Empty; if (e.Request.RawUrl.Contains("?")) { int index = e.Request.RawUrl.IndexOf("?"); action_name = e.Request.RawUrl.Substring(0, index); } else action_name = e.Request.RawUrl; if (dict.ContainsKey(action_name)) { requestAction = dict[action_name]; object first_para_obj; object[] para_values_objs = new object[requestAction.ParameterInfo.Length]; //没有参数,默认为空对象 if (requestAction.ParameterInfo.Length == 0) { first_para_obj = new object(); } else { int para_count = requestAction.ParameterInfo.Length; for (int i = 0; i < para_count; i++) { var para = requestAction.ParameterInfo[i]; if (para.GetCustomAttributes(typeof(FromBodyAttribute), false).Any()) { //反序列化Json对象成数据传输对象 var dto_object = para.ParameterType; para_values_objs[i] = JsonConvert.DeserializeObject(content, dto_object); } else { //参数含有FromBodyAttribute的只能有一个,且必须是第一个 int index = e.Request.RawUrl.IndexOf("?"); if (e.Request.RawUrl.Contains("&")) { bool existsFromBodyParameter = false; foreach (var item in requestAction.ParameterInfo) { if (item.GetCustomAttributes(typeof(FromBodyAttribute), false).Any()) { existsFromBodyParameter = true; break; } } string[] url_para = e.Request.RawUrl.Substring(index + 1).Split("&".ToArray(), StringSplitOptions.RemoveEmptyEntries); if (existsFromBodyParameter) para_values_objs[i] = url_para[i - 1].Replace(para.Name + "=", ""); else para_values_objs[i] = url_para[i].Replace(para.Name + "=", ""); } else { para_values_objs[i] = e.Request.RawUrl.Substring(index + 1).Replace(para.Name + "=", ""); } } } } var action = container.Resolve(requestAction.ControllerType); var action_result = requestAction.Action.Invoke(action, para_values_objs); if (action_result == null) { e.Response.StatusCode = 204; } else { e.Response.StatusCode = 200; if (requestAction.Action.ReturnType.Name.Equals("ApiActionResult")) { e.Response.ContentType = "application/json"; byte[] buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(action_result)); e.Response.WriteContent(buffer); } if (requestAction.Action.ReturnType.Name.Equals("agvBackMessage")) { e.Response.ContentType = "application/json"; byte[] buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(action_result)); e.Response.WriteContent(buffer); } else if (requestAction.Action.ReturnType.Name.Equals("HtmlResult")) { HtmlResult result = (HtmlResult)action_result; e.Response.ContentType = result.ContentType; byte[] buffer = result.Encoder.GetBytes(result.Content); e.Response.WriteContent(buffer); } else if (requestAction.Action.ReturnType.Name.Equals("ImageResult")) { ImageResult apiResult = (ImageResult)action_result; e.Response.ContentType = apiResult.ContentType; byte[] buffer = Convert.FromBase64String(apiResult.Base64Content.Split(",".ToArray(), StringSplitOptions.RemoveEmptyEntries).LastOrDefault()); e.Response.WriteContent(buffer); } else { byte[] buffer = Encoding.UTF8.GetBytes(action_result.ToString()); e.Response.WriteContent(buffer); } } } else { e.Response.StatusCode = 404; } } catch (Exception ex) { if (requestAction.ExceptionFilter == null) { byte[] buffer = Encoding.UTF8.GetBytes(ex.Message + ex.StackTrace); e.Response.WriteContent(buffer); e.Response.StatusCode = 500; } else { if (requestAction.ExceptionFilter != null) { if (ex.InnerException != null) { requestAction.ExceptionFilter.OnException(ex.InnerException, e); } else { requestAction.ExceptionFilter.OnException(ex, e); } } } } }
三、体验概述
- 1、稳,可用性很高,简单直接。
- 2、使用之后对mvc的底层理解提高很多。
- 3、对Autofac等IOC容器有了新的认识,项目里大量使用了属性注入方式来解除耦合。
四、一些截图
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++