C#桌面程序(winform)如何一步步集成内置WebApi(owin技术),解耦IIS,并将Api接收信息推给桌面窗体控件展示
最近工厂有个需求,服务器上部署了一个服务,此服务要把信息推送给现场多台工控机上的CS上位机程序。由于涉及到多个软件之间的通信,做架构时,首先排除掉中间表形式,从效率和稳定性上也排除掉了Socket,最后采用了WebApi接口形式来做通信。但是有个问题,上位机程序都为运行稳定的CS架构程序,当时并没有考虑后台服务WebApi的需求。如果现在给每个上位机程序再做个后端WebApi部署在IIS上,那势必会造成很多开发资源浪费(制造业IT嘛,本身开发就那么几个,呵呵~)。
所以后来思考,能不能做个内置WebApi的dll包,方法事件都写好,上位机软件只要加载这个dll包就能在本地上位机上跑WebApi服务,接收并处理WebApi接收到的消息,大大减小大家的开发工作量。结果还真有办法,就是使用owin技术。owin是什么,大家可以百度下,大致意思就是它允许你在本地运行WebService,从而解耦web服务器IIS。
那怎么集成owin呢,方法如下:
一、创建dll项目及导入所需依赖库
打开VS,建立class library项目,命名为OWINServer
打开Nuget,导入下列所需依赖库
二、建立Startup类
在OWINServer项目中,创建第一个类Startup类,用以启动owin
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
try
{
HttpConfiguration config = new HttpConfiguration();
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
catch (Exception ex)
{
throw ex;
}
}
}
三、建立事件类TriggerEvent
在OWINServer项目中,建立第二个类OWINTriggerEvent事件类,用来保存接口收到的信息,并用事件触发的方式将收到的接口信息通知桌面应用。
public class OWINTriggerEvent
{
public delegate void GetInfoEventHandler(object sender, EventArgs e);
public event GetInfoEventHandler infoEvent;
//存储信息变量
public string Message = "";
//编写引发事件的函数(在程序任意域使用)
public void OnMessage()
{
if (infoEvent != null)
{
//发送信息
infoEvent(this, new EventArgs());
}
}
}
四、建立ApiController接口类
在OWINServer项目中,建立第三个类OWINApiController,用以实现被外部调用的接口。当收到信息后触发OWINTriggerEvent事件,将消息传给桌面前端应用。
public class OWINApiController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "Success"};
}
// GET api/<controller>/5
public string Get(int id)
{
return string.Format("owin {0} by:linezero", id);
}
// POST api/<controller>
public string Post([FromBody] string value)
{
//将接收到的信息赋给事件类中Message属性
OWINStart.TriggerEvent.Message = value;
//触发事件类中事件,将消息传递给桌面程序绑定的方法
OWINStart.TriggerEvent.OnMessage();
return "Success";
}
// PUT api/<controller>/5
public string Put([FromBody] string value)
{
return "Success";
}
// DELETE api/<controller>/5
public string Delete([FromBody] string value)
{
return "Success";
}
}
这里只在Post接口里,写了简单接收消息和触发事件的代码,各位可根据需要在里面写其他逻辑代码,但还是建议里面不多写逻辑,功能界限只作为消息传递,将消息传递给桌面前端后,由前端对消息进行分析处理。
五、建立OWINStart类
上面3个工具类写完后,再写个集成类OWINStart,用以对以上3个类集成,作为对外的唯一调用类,方便第三方软件对OWINServer.dll的使用。
public class OWINStart
{
public static OWINTriggerEvent TriggerEvent { get; set; }
public static OWINTriggerEvent Start(string ServerUrl)
{
try
{
//调用Startup启动owin,url需要调用方传入
WebApp.Start<Startup>(url: ServerUrl);
//新建OWINTriggerEvent类实例,并返回被调用方使用获取里面的message和infoEvent事件
var triggerEvent = new OWINTriggerEvent();
TriggerEvent = triggerEvent;
HttpClient client = new HttpClient();
//通过get请求数据,测试owin服务是否正常开启
var response = client.GetAsync(ServerUrl+"api/owinapi").Result;
if (response.IsSuccessStatusCode)
{
return triggerEvent;
}
else
{
throw new Exception("Owin loacal server start failed!");
}
}
catch (Exception)
{
throw;
}
}
}
六、编译OWINServer项目,获得dll文件
项目结构如下,直接编译项目
获得如下dll文件
OWINServer.dll包通过前面6步就已经生成了,下面就是创建个桌面引用,集成并测试一下它好不好用了~
七、新建桌面项目,导入OWINServer.dll
新建一个owin的桌面项目,将OWINServer.dll包导入
简单画几个桌面控件,按钮用来启动owin,一个输入框用来输入开启的owin服务的url地址,另一个用来显示接口接到的消息。
八、启动owin服务,接收并显示消息
在winform后端写如下代码,调用OWINStart.Start启用owin服务,并给infoEvent事件绑定处理方法GetInfo()。
public partial class Form1 : Form
{
private OWINTriggerEvent _triggerEvent;
public Form1()
{
InitializeComponent();
}
private void Start_button_Click(object sender, EventArgs e)
{
try
{
if (textBox2.Text != "")
{
;
string baseAddress = "http://" + textBox2.Text + ":9121/";
_triggerEvent = OWINStart.Start(baseAddress);
_triggerEvent.infoEvent += GetInfo;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void GetInfo(object sender, EventArgs e)
{
try
{
//将接口收到的消息传给textbox控件
Action actionDelegate = () => { this.textBox1.Text = _triggerEvent.Message; };
this.textBox1.Invoke(actionDelegate);
}
catch (Exception ex)
{
throw;
}
}
}
写完后,运行winform,点击Start按钮,随后打开postman进行接口调试。
可以发现postman成功的将信息通过调用owin接口,将信息传给了桌面的textbox控件。
九、注意事项
(1)调用OWINServer.dll可能会报找不到依赖包的错误,请检查第6步中的dll包是否都放在你的项目dll文件夹中和OWINServer.dll文件在一起。
如果还是报Could not load file or assembly ‘Microsoft.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)”:”Microsoft.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35错误
请在app.config中加如以下指向代码:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.9.0" newVersion="5.2.9.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.9.0" newVersion="5.2.9.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
(2)最近在调试中又出现一个新的问题,发现在调试程序的时候WebApp.Start(url: ServerUrl)可以成功执行,并开启服务。但是跑生成的执行程序时就会报异常错误,啥异常也没说明,只是报内部异常。尝试了N多次,加了N个log也没找到问题,最后查阅资料,发现这原来是缺少管理员权限,而引起了一个被拒绝的内部异常。用管理员权限打开执行程序可以正常开启服务并打开程序。
结语
以上就实现了桌面程序内置WebApi,可以用来进行软件之间的通信。当有软件需要使用此webApi功能时,只要导入这个OWINServer.dll包即可。
dll包下载地址:https://download.csdn.net/download/weixin_44239774/87155725
欢迎各位留言交流,需要源代码和dll包的可以留下邮箱~
文章出处登录后可见!