一、背景

  因为需要做金蝶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容器有了新的认识,项目里大量使用了属性注入方式来解除耦合。

四、一些截图

最新文章

  1. 转载:安装ie driver和chrome driver
  2. 35.两链表的第一个公共结点[Find the first common node of two linked list]
  3. 【001:go语言的一些语法基础】
  4. Java变量自增和自减运算符的用法
  5. Java程序员面试宝典——重要习题整理
  6. MAMP Pro3.5注册码
  7. android125 zhihuibeijing 缓存
  8. Prince and Princess
  9. preventDefault() 方法 取消掉与事件关联的默认动作
  10. cmake学习笔记(五)
  11. [iOS Animation]-CALayer 图层树
  12. Android权限解释
  13. UVa225,Golygons
  14. 现代Java进阶之路必备技能——2019 版
  15. 使用Node.js+Hexo+Github搭建个人博客
  16. [MV] - You Give REST a Bad Name
  17. Html+css学习笔记二 标题
  18. System.Data.SqlClient.SqlException: 数据类型 text 和 varchar 在 equal to 运算符中不兼容。
  19. 赵丽颖固然漂亮,可这份Hadoop核心教程也不差呀
  20. Asp.net MVC 控制器扩展方法实现jsonp

热门文章

  1. linux安装redis步骤
  2. 嵌入式Linux+NetCore 笔记一
  3. 4、Ext.NET 1.7 官方示例笔记 - 树
  4. Linux软件安装——安装软件的命令
  5. PMP备考-第三章-项目管理过程
  6. 英文DIAMAUND钻石DIAMAUND词汇
  7. 章节十四、3-执行JavaScript命令
  8. 处理 JS中 undefined 的 7 个技巧
  9. 转:oracle笔记
  10. Django 简单评论实现