开源组件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);}elseaction_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 + "=", "");elsepara_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容器有了新的认识,项目里大量使用了属性注入方式来解除耦合。
四、一些截图
转载于:https://www.cnblogs.com/datacool/p/websocket-sharp.html
开源组件websocket-sharp中基于webapi的httpserver使用体验相关推荐
- 开源组件 Ehcache中被曝严重漏洞,影响多款Jira产品
聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士 Atlassian 公司督促企业客户修复其 Jira Data Center 和 Jira Service Management Data ...
- Winform中使用EasyPlayer-RTSP-Win开源组件实现播放RTSP视频流
场景 开源RTMP组件EasyPusher-Android+EasyDarwin实现APP推流给RTSP流媒体服务器: 开源RTMP组件EasyPusher-Android+EasyDarwin实现A ...
- Java 代码基于开源组件生成带头像的二维码
二维码在我们目前的生活工作中,随处可见,日常开发中难免会遇到需要生成二维码的场景,网上也有很多开源的平台可以使用,不过这里我们可以通过几个开源组件,自己来实现一下. 在动手之前我们先思考一下需要进行的 ...
- Java 代码基于开源组件生成带头像的二维码,推荐收藏
二维码在我们目前的生活工作中,随处可见,日常开发中难免会遇到需要生成二维码的场景,网上也有很多开源的平台可以使用,不过这里我们可以通过几个开源组件,自己来实现一下. 在动手之前我们先思考一下需要进行的 ...
- vue tree组件_基于 Vue2.0 和 HeyUI 组件库的中后端系统 HeyUI Admin
介绍 heyui-admin 是一个成熟的企业应用解决方案,基于 vue2.0 和 heyui 组件库的中后端系统. 功能 - Js - common / 通用 - ajax / 封装axios - ...
- 后端常用开源组件合集(持续更新中)
1. 常用库 awesome - golang开源库集合 2. 编码规范 cppguide - C++编码规范 CodeReviewComments - go code review建议 3. 敏捷开 ...
- Uncode系列开源组件简介
概述 Uncode 是基于Java 语言的一系列企业级开源组件,作者冶卫军 (开源作者花费大量时间维护开源项目,期望正确使用).主要包括:移动后端开发框架Uncode-BaaS ,通用数据库访问组件U ...
- 开源组件ExcelReport 1.5.2 使用手册
ExcelReport是一款基于NPOI开发的报表引擎组件.它基于关注点分离的理念,将数据与样式.格式分离.让模板承载样式.格式等NPOI不怎么擅长且实现繁琐的信息,结合NPOI对数据的处理的优点将E ...
- 开源组件是什么意思_一文读懂常用开源许可证
社区时常为流行产品中有争议的开源许可证而感到震惊,这引起各方关注,纷纷争论何为真正的开源许可证.去年,Apache 基金会(Apache Foundation)禁止使用 Facebook React ...
最新文章
- 用 Redis 处理 jsonwebtoken 生成的 Token
- 使用TensorFlow训练WDL模型性能问题定位与调优
- iOS核心动画之CALayer-隐式动画
- 事业单位计算机初级考试科目一模拟试题,广东教师资格考试之科目一模拟题
- 【2017年第3期】面向共享的政府大数据质量标准化问题研究
- app抢购脚本如何编写_如何用1个记事本文件征服全世界?——cmd批处理脚本编写...
- NLP --- 条件随机场CRF背景
- 系统集成项目管理工程师 案例题【2021上】 总结
- PYTHON对接验证码短信接口DEMO示例
- JavaScript 编程精解 中文第三版 五、高阶函数
- PHP中的定界符 echo
- ivms虚拟服务器,ivms监控服务器地址
- 程序员常用刷题网站分享
- Flash和XML实现电子地图查询及定位功能
- OSG 中 常用的 Uniforms
- Linux下使用 shell 脚本实现ftp文件下载
- 【数据库02】==== 表的增删改查(基础)
- React Native 炫酷的动画库 实现任何AE动画 lottie-react-native
- justify-content具体属性值
- 谷歌浏览器播放视频没有声音解决
热门文章
- zeroclipboard 粘贴板的应用示例, 兼容 Chrome、IE等多浏览器
- libgstreamer-1.0.so.0: cannot open shared object file: No such file or directory
- Python 标准库之 json
- django自带的分页功能
- Kali2021.2 VMware最新版安装步骤
- 数据库里存json数据
- tf.placeholder函数说明
- GOF23设计模式(创建型模式)建造者模式
- AI 芯片的分类及技术
- HarmonyOS技术特性