开源组件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容器有了新的认识,项目里大量使用了属性注入方式来解除耦合。
四、一些截图


开源组件websocket-sharp中基于webapi的httpserver使用体验的更多相关文章
- itest 开源测试管理项目中封装的下拉列表小组件:实现下拉列表使用者前后端0行代码
导读: 主要从4个方面来阐述,1:背景:2:思路:3:代码实现:4:使用 一:封装背景 像easy ui 之类的纯前端组件,也有下拉列表组件,但是使用的时候,每个下拉列表,要配一个URL ...
- 开源组件ExcelReport 1.5.2 使用手册
ExcelReport是一款基于NPOI开发的报表引擎组件.它基于关注点分离的理念,将数据与样式.格式分离.让模板承载样式.格式等NPOI不怎么擅长且实现繁琐的信息,结合NPOI对数据的处理的优点将E ...
- .net 开源组件
文章转自:http://www.cnblogs.com/asxinyu/p/dotnet_opensource_project_3.html 在前2篇文章这些.NET开源项目你知道吗?让.NET开 ...
- Android自定义控件 开源组件SlidingMenu的项目集成
在实际项目开发中,定制一个菜单,能让用户得到更好的用户体验,诚然菜单的样式各种各样,但是有一种菜单——滑动菜单,是被众多应用广泛使用的.关于这种滑动菜单的实现,我在前面的博文中也介绍了如何自定义去实现 ...
- 如何在WebSocket类中访问Session
我最近正在做一个基于websocket的webQQ,最后代码会开源带github上,所以过程中我就不贴所有的代码啦~就贴问题的关键. 我在WebSocket里发消息的时候需要用到session,因为在 ...
- BeetleX高性能通讯开源组件
net core高性能通讯开源组件BeetleX https://www.cnblogs.com/smark/p/9617682.html BeetleX beetleX是基于dotnet core实 ...
- 微信开源组件WCDB漫谈及Demo
代码地址如下:http://www.demodashi.com/demo/12422.html 前言 移动端的数据库选型一直是一个难题,直到前段时间看到了WeMobileDev(微信前端团队)放出了第 ...
- 饿了吗开源组件库Element模拟购物车系统
传统的用html+jquery来实现购物车系统要非常的复杂,但是购物车系统完全是一个数据驱动的系统,因此采用诸如Vue.js.angular.js这些框架要简单的多.饿了吗开源的组件库Element是 ...
- 如何利用阿里视频云开源组件,快速自定义你的H5播放器?
摘要: Aliplayer希望提供一种方便.简单.灵活的机制,让客户能够扩展播放器的功能,并且Aliplayer提供一些组件的基本实现,用户可以基于这些开源的组件实现个性化功能,比如自定义UI和自己A ...
随机推荐
- windows 安装gitea
gitea 地址https://github.com/go-gitea/gitea windows 安装
- maven聚合项目以及使用dubbo远程服务调用debug操作。
1.maven聚合项目以及使用dubbo远程服务调用debug操作. 然后操作如下所示: 然后如下所示: 启动断点所在的包的服务.以debug的形式启动. 断点进来的效果如下所示: 接下来请继续你的表 ...
- SQL学习笔记之 数据库基础(一)
数据库基础 数据库系统的组成:由数据库,数据库管理软件,数据库管理员DBA,支持数据库系统的硬件和软件组成,其中数据库管理员是对数据库进行规划.设计.维护.和监视的专业管理人员,在数据库系统中起着非常 ...
- NetCoreApi框架搭建(一、swagger插件使用)
1.首先用vs2017创建新的项目 2.开始引入swagger插件 右击项目=>管理NuGet程序包=>搜索Swashbuckle.AspNetCore点击安装 3.打开Startup.c ...
- 2019 梆梆安全java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.梆梆安全等公司offer,岗位是Java后端开发,因为发展原因最终选择去了梆梆安全,入职一年时间了,也成为了面 ...
- Windows中将nginx添加到服务(转)
下载安装nginx http://nginx.org/en/download.html 下载后解压到C盘 C:\nginx-1.14.0 添加服务 需要借助"Windows Service ...
- python3匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便. 在Python中,对匿名函数提供了有限支持.还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外, ...
- 如何在浏览器中运行 VS Code?
摘要: WEB IDE新时代! 作者:SHUHARI 的博客 原文:有趣的项目 - 在浏览器中运行 Visual Studio Code Fundebug按照原文要求转载,版权归原作者所有. 众所周知 ...
- 在VideoFileClip函数中获取“OSError:[WinError 6]句柄无效”
我正在使用python通过导入moviepy库创建一个程序,但收到以下错误: from moviepy.editor import VideoFileClip white_output = 'vide ...
- 一次http请求的过程
http协议(超文本传输协议)是属于应用层的协议,网络分层:应用层(http协议,FTP),传输层(tcp,udp),网络层(ip/ARP),链路层 我们以浏览器向百度发送请求为例: http的发送: ...