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控件。
九、注意事项
调用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>
结语
以上就实现了桌面程序内置WebApi,可以用来进行软件之间的通信。当有软件需要使用此webApi功能时,只要导入这个OWINServer.dll包即可。 dll包下载地址:https://download.csdn.net/download/weixin_44239774/87155725 欢迎各位留言交流,需要源代码和dll包的可以留下邮箱~