上一篇博客介绍了以WCF的方式,在后端程序部署WEB接口,本篇介绍以WebApi的方式以后端程序为宿主部署WEB接口,依旧以本人实际开发的项目进行说明,直接进入正题。
材料:VS2015,框架:.NET FrameWork 4.5.2,接口调试工具:PostMan,数据传输格式:Json。
本人的项目程序是Windows服务程序,各位自测的时候可以新建一个控制台程序,是一样的哈。
下图为本人的项目文件类库:(供参考)
packages.config
下图为项目需要使用的引用文件,除了Lx.CSharp.Common(这个是个人封装的通用方法库文件)不需要管,YiriXXXX是工程下的相关类库依赖引用,也可以不需要管,上图BLL文件夹下为业务处理的代码,读者也可以不用管,其他的引用文件都是项目中需要使用的引用,这些引用文件大部分在本地计算中就可以找到(除非你的.NET FrameWork版本够旧的),找不到的话就网上搜索NUGET方法就可以了(提示:System.Web.Http需要NuGet “Microsoft.AspNet.WebApi.Core”)。
了解过WebApi的朋友应该知道,有一个叫“路由”的东西很重要,这个东西规定了前端访问接口的调用方法,类库图中的文件夹Api_Start下的类StartUp就是路由代码。代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using Newtonsoft.Json;
using System.Net.Http.Formatting;
using Owin;
using System.Web.Http.Cors;
namespace YiriFloodMonitoringSystemService.SendDataToSensor.Api_Start
{
public class StartUp
{
public void Configuration(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.EnableCors(new EnableCorsAttribute("*", "*", "*")); //配置跨域(EnableCors方法需要NuGetMicrosoft.AspNet.WebApi.Cors)
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new
{
id = RouteParameter.Optional
}
);
//清除xml格式,使用json格式
config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
appBuilder.UseWebApi(config); //UseWebApi方法需要NuGet "Microsoft.AspNet.WebApi.Owin"
}
}
}
其中关键的地方为:"api/{controller}/{action}/{id}",这就是WebApi的路由规则,格式翻译为:api / 控制器名称 / 接口方法名称 / 参数ID,WebApi的相关路由规则,读者可以到网上自行搜索了解,这里不多做赘述.(推荐链接:WebApi路由机制详解——看完不会用你打我_webapi 路由_changuncle的博客-CSDN博客)
接下来分别是接口定义和模型的代码(完整代码太多,取部分,供参考):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YiriFloodMonitoringSystemService.SendDataToSensor.Model;
namespace YiriFloodMonitoringSystemService.SendDataToSensor.SendDataInterface
{
interface RD_600_Interface
{
string SetRoundChannalMulti(RoundChannalParamArr_RD600 channalArr);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YiriFloodMonitoringSystemService.SendDataToSensor.Model
{
public struct RoundChannalParam_RD600
{
public string siteId;
public byte port;
public byte addr;
public float distance;
public float radius;
public DateTime sendTime;
}
public class RoundChannalParamArr_RD600
{
public RoundChannalParam_RD600[] RoundChannalParamObjArr { get; set; }
}
}
至此,可以与上一篇以WCF的方式开发Web接口相比,可以发现,无论是接口定义还是数据的结构模型,相比下webapi显得更轻型,没有非常多的契约、规则等相关的书写规定,完完全全的普通的接口和数据模型。这里需要注意的一个参数是RoundChannalParamObjArr ,一会调试的时候就会知道。
接下看接口实现代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Http;
using YiriFloodMonitoringSystemService.SendDataToSensor.Model;
using YiriFloodMonitoringSystemService.SendDataToSensor.SendDataInterface;
using System.Threading;
using YiriFloodMonitoringSystemService.SendDataToSensor.BLL;
using YiriFloodMonitoringSystemService.Common.Logs;
using YiriFloodMonitoringSystemService.Trigger;
namespace YiriFloodMonitoringSystemService.SendDataToSensor.SendDataRealize
{
public class RD_600_RealizeController : ApiController, RD_600_Interface
{
[HttpPost]
public string SetRoundChannalMulti(RoundChannalParamArr_RD600 channalArr)
{
try
{
SensorDataTrigger.Instance().Stop();
StringBuilder jsonBuilder = new StringBuilder();
jsonBuilder.Append("{\"");
jsonBuilder.Append("result");
jsonBuilder.Append("\":[");
SetChannalParamBusiness_RD600 objSetChannalParamBusiness = new SetChannalParamBusiness_RD600();
BusinessCommon objBusinessCommon = new BusinessCommon();
for (int i = 0; i < channalArr.RoundChannalParamObjArr.Length; i++)
{
RoundChannalParam_RD600 objRoundChannalParam = channalArr.RoundChannalParamObjArr[i];
int identityId = objBusinessCommon.InsertObject(objRoundChannalParam, EmSendClass.ChannalParam);
jsonBuilder.Append("{");
jsonBuilder.Append("\"");
jsonBuilder.Append(string.Format("{0}|{1}|{2}", objRoundChannalParam.siteId, objRoundChannalParam.port, objRoundChannalParam.addr));
jsonBuilder.Append("\":\"");
string result = objSetChannalParamBusiness.SetRoundChannalMultiBLL(objRoundChannalParam);
Thread.Sleep(500);
objBusinessCommon.UpdateObject(identityId, result.Contains("成功") ? true : false, result.Contains("成功") ? string.Empty : result);
jsonBuilder.Append(result);
jsonBuilder.Append("\"");
jsonBuilder.Append("},");
}
if (jsonBuilder.ToString().LastIndexOf(',') == jsonBuilder.Length - 1)
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
jsonBuilder.Append("]");
jsonBuilder.Append("}");
string jsonResult = jsonBuilder.ToString();
return jsonResult;
}
catch (Exception ex)
{
SendDataLog.LogException(ex);
Thread.Sleep(10);
return string.Empty;
}
finally
{
SensorDataTrigger.Instance().Start();
}
}
}
}
方法里面的业务处理读者在测试时可以自己编写,此处仅仅为了贴上完整代码而已。此处几个关键点为:
1、控制器名称RD_600_RealizeController,我们在路由设置中知道有控制器名称的规定,此处的 RD_600_Realize 即为其控制器名称,是的,不是 RD_600_RealizeController,而是 RD_600_Realize。
2、控制器必须继承ApiController,只有继承ApiController,才能被前端调用到,然后继承 RD_600_Interface 接口只是为了实现接口。(其实是可以不需要写接口代码的,直接写控制器代码就可以,只是为了规范化,所以加了接口代码)。
3、[HttpPost],该处定义了接口的调用方式为POST。其实,WebApi 遵循 RestFul 规则,如果按规则定义方法名称,[HttpPost] 的定义也可以不要,至于什么是 RestFul 规则,读者可以在网上自行搜索。
接下来看,模块的启动类,实际上就是启动了线程中的任务而已,完整代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using YiriFloodMonitoringSystemService.SendDataToSensor.Api_Start;
using YiriFloodMonitoringSystemService.Common.Logs;
namespace YiriFloodMonitoringSystemService.SendDataToSensor
{
public class SendDataMain
{
private Thread sendDataMainThread = null;
private static SendDataMain sm_singleInstance = null;
private static readonly object locks = new object();
public static SendDataMain Instance() //单例
{
if (sm_singleInstance == null)
{
lock (locks)
{
if (sm_singleInstance == null)
{
sm_singleInstance = new SendDataMain();
}
}
}
return sm_singleInstance;
}
public SendDataMain()
{
sendDataMainThread = new Thread(new ThreadStart(StartWebApi));
sendDataMainThread.IsBackground = true;
}
public void Start()
{
sendDataMainThread.Start();
}
public void Stop()
{
sendDataMainThread.Abort();
}
private void StartWebApi()
{
IPAddress localIp = null;
IPAddress[] ipArray;
try
{
ipArray = Dns.GetHostAddresses(Dns.GetHostName());
localIp = ipArray.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);
if (localIp == null)
{
localIp = IPAddress.Parse("127.0.0.1");
}
string ipStr = string.Format("http://{0}:5959", localIp);
StartOptions options = new StartOptions();
options.Urls.Add("http://localhost:5959");
options.Urls.Add("http://127.0.0.1:5959");
options.Urls.Add(ipStr);
WebApp.Start<StartUp>(options);
SendDataLog.LogInfo("WebApi Start......");
}
catch (Exception ex)
{
SendDataLog.LogException(ex);
}
}
}
}
接下来,在 Main() 方法中启动线程(调用 Start() 方法)就可以启动此 WebApi 服务了。
然后看接口调用(使用POSTMAN接口调试工具):
至此,以后端程序为宿主的WebApi 接口代码就完成了。对比WCF来说,个人感觉 WebApi 的接口更加清爽、简洁,省去了很多契约、规定等等的书写,让程序开发者能更专注于接口业务内容的开发而不是接口的部署。
本文章作者纯手码字,若有引用部分已在文章中注明出处地址,如有侵权,请及时联系作者删除。如有雷同,万分荣幸。如果错误或者疑问,请在留言区留言,本人看到后会及时回复。
感谢阅读!