业务需求那些事,使用WCF如何实现业务需求!
最近遇到一个新项目,需要与硬件结合,进行读取信息并保存在数据库中。业务要求也在昨天发布一个问题,当然感谢许多园内的朋友出谋划策,截图有真相!
关于这个问题,我做了如下假设。目前处于测试状态,代码比较简单,具体功能已经实现。
1、首先一张比较丑的图片表名业务逻辑关系。
用户customer 他可以去A B C D 四个办事处去登记信息。这样假设每个办事处有一个登记人员,假设customer 选择了 A ,(可能是离A比较近,他不想跑了)
登记人员说出示的卡。登记人员就把的卡往Arecorder 一放,点击鼠标,用户的信息就可以显示到web界面上了。看到这里是不是感觉很简单,不就是Arecorder 把customer的信息发送给web页面了吗?
你说的没有错,就是这么简单。那简单咱就技术实现吧。
技术实现:需要考虑哪些问题。
1》 A recorder 只是一台具有连接网络或者局域网的计算机。 web 服务管理也不是部署在 A recorder 计算机上的,当然大家知道是部署在服务器上的。那么问题来了。要实现web服务器与Arecorder之间的通信怎么实现呢?
这也难不倒你,网络传输tcp socket编程。。。不难。这里对于这个问题,我们不做深入探究。我使用的是WCF技术。
2》 好了,web服务与A recorder 通信的问题解决了,那就写程序白。。。。。,半个小时过去了,你的编码速度很牛啊,service端和client的代码都搞定了,现在就测试可不可以呢。说道这里,service端的代码发布到与web服务IIS上面去,client代码当然去监控A recorder了,这里本来没有任何问题,我们知道service 的程序时一直运行的,它们之间的关系可以简单一张图表示,当然只是简单的 request-response模式。
看到这里,你可能发现问题。我应该何时请求呢,我贴卡的时候去Request,这是个好主意,Request 发送到哪里呢,肯定是service呀,不然还能发送到哪了,哈,那么问题来了? web服务管理不是给你一个人使用的,也就是说有好多人都在使用这套管理系统,可能赵四 王五 都在 登记用户信息,好你拿着custmoer的卡一刷,Request 就发送出去了,那么它会发送到你打开的web 页上吗???,或者发送到 赵四、或者王五的打开的页面上呢,那么这样这么多不确定性,确实不好办呢。怎么办???赶紧想呀,经理崔项目呢。。。
3》 时间一点一点过去,你想呀,突然脑袋灵光一现,为什么我非要等到customer刷卡的时,去Request呢,我为什么不能使登记人员去把握Request呢。而 A recorder 成为service呢。这样之间的关系不就清楚了吗。是呀到这里,恭喜你。那还等什么赶紧code呀。。。。,测试下,果然不错。哈哈哈。
4》经理说,我们不是需要一个A recorder,而是有 B C D 。。。,你一个都搞定了,多加几个也是没有问题的吧。瞬间整个人都不好了。。。,经理说了那也上呀,多个录卡器,多个工作登记人员,要想实现信息登录的正确性,怎么办,web服务又是大家共享的,顺着思路想下去,。。。。,多个Recorder,那就要区分每个Recorder,那好办,每个都绑定一个固定的IP不就可以了吗? 然后让web request ,好呀,干嘛,code呀。。。。,不对,我web request 了,那我应该需要的是哪个recorder的信息呢,怎么办? 这可能会造成我把别的customer的信息请求过来的。要是事先能知道Request哪一个就好了,怎么办,那就让登记人员,在请求的时候把选中那个recorder。不就可以了吗。是呀,如图:
5》到这里,通过分析已经找到了,解决方案,那么接下来要看编程技术了,这里只是简单的分享下。
coding: Recorder 端的代码。wcf基本结构四层结构;
Contract:
1---》IOctorpusService.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.ServiceModel; 6 namespace DataWorld.Octorpus.Contract 7 { 8 [ServiceContract] 9 [ServiceKnownType(typeof(RecordMintor))] 10 public interface IOctorpusService 11 { 12 [OperationContract] 13 [FaultContract(typeof(OctorException))] 14 string GetOctorpusNo(); 15 } 16 }
2----》OctorException.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.Serialization; 6 namespace DataWorld.Octorpus.Contract 7 { 8 [DataContract] 9 public class OctorException 10 { 11 #region 私有类 12 private string _operation; 13 private string _errorMessage; 14 #endregion 15 #region 构造函数 16 public OctorException(string operation, string errorMessage) 17 { 18 this._operation = operation; 19 this._errorMessage = errorMessage; 20 } 21 #endregion 22 #region 公共方法 23 [DataMember] 24 public string Operation 25 { 26 get { return _operation; } 27 set { _operation = value; } 28 } 29 [DataMember] 30 public string ErrorMessage 31 { 32 get { return _errorMessage; } 33 set { _errorMessage = value; } 34 } 35 #endregion 36 37 } 38 }
3----》RecordMintor.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.Serialization; 6 namespace DataWorld.Octorpus.Contract 7 { 8 [DataContract] 9 public class RecordMintor 10 { 11 #region 私有字段 12 private string _CarNo; 13 private string _OctorpusNo; 14 #endregion 15 #region 构造函数 16 public RecordMintor(string carno, string octorpusno) 17 { 18 this._CarNo = carno; 19 this._OctorpusNo = octorpusno; 20 } 21 #endregion 22 #region 公共属性 23 [DataMember] 24 public string CarNo 25 { 26 get { return _CarNo; } 27 set { _CarNo = value; } 28 } 29 [DataMember] 30 public string OctorpusNo 31 { 32 get { return _OctorpusNo; } 33 set { _OctorpusNo = value; } 34 } 35 #endregion 36 } 37 }
Service:
1--》OctorpusService.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using DataWorld.Octorpus.Contract; 6 namespace DataWorld.Octorpus.Service 7 { 8 public class OctorpusService:IOctorpusService 9 { 10 11 public string GetOctorpusNo() 12 { 13 // OctorException oe = new OctorException("Server exception", "Restart server"); 14 15 RecordMintor rm = new RecordMintor(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); 16 //throw new NotImplementedException(); 17 Console.WriteLine(rm.CarNo); 18 return rm.OctorpusNo; 19 } 20 } 21 }
hosting:
1--》 program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DataWorld.Octorpus.Service; using System.ServiceModel; namespace DataWorld.Octorpus.Hosting { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(OctorpusService))) { host.Opened += delegate { Console.WriteLine("listening..."); }; host.Open(); Console.Read(); } } } }
2--》App.config
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <system.serviceModel> 4 <bindings> 5 <wsHttpBinding> 6 <binding name="wsHttpBinding"> 7 <security mode="None"> 8 </security> 9 </binding> 10 </wsHttpBinding> 11 </bindings> 12 <behaviors> 13 <serviceBehaviors> 14 15 <behavior name="OctorpusServiceBehavior"> 16 <serviceMetadata httpGetEnabled="true"/> 17 </behavior> 18 </serviceBehaviors> 19 </behaviors> 20 <services> 21 <service name="Company.Octorpus.Service.OctorpusService" behaviorConfiguration="OctorpusServiceBehavior"> 22 <endpoint address="" binding="wsHttpBinding" contract="Company.Octorpus.Contract.IOctorpusService" bindingConfiguration="wsHttpBinding"/> 23 <host> 24 <baseAddresses> 25 <add baseAddress="http://192.168.19.56:9999/Service"/> 26 </baseAddresses> 27 </host> 28 </service> 29 </services> 30 </system.serviceModel> 31 </configuration>
client:我写在了web中;
AutoGetCarNO.ashx
1 using System; 2 using System.Collections.Generic; 3 using System.Web; 4 5 namespace fairviewweb.Management 6 { 7 /// <summary> 8 /// Summary description for AutoGetCarNO 9 /// </summary> 10 public class AutoGetCarNO : IHttpHandler 11 { 12 private DateTime _endTime; 13 private bool _IsEndFlag = false; 14 private string _msg=null; 15 private Maticsoft.BLL.t_Recorder tbll = new Maticsoft.BLL.t_Recorder(); 16 public void ProcessRequest(HttpContext context) 17 { 18 context.Response.ContentType = "text/plain"; 19 string CarNodroplist = context.Request.QueryString["CarNodroplist"] == null ? string.Empty : context.Request.QueryString["CarNodroplist"].ToString(); 20 Maticsoft.Model.t_Recorder tmodel= tbll.GetModel(CarNodroplist.Trim()); 21 this._endTime=DateTime.Now.AddSeconds(4); 22 switch (tmodel.IPADDRESS) 23 { 24 case "ServiceReferenceA": try 25 { 26 ServiceReference1.OctorpusServiceClient _octorpusNO = new ServiceReference1.OctorpusServiceClient(); 27 this._msg = _octorpusNO.GetOctorpusNo(); 28 while (!_IsEndFlag) 29 { 30 31 if (!string.IsNullOrEmpty(this._msg)) 32 { 33 _IsEndFlag = true; 34 } 35 if (this._endTime <= DateTime.Now) 36 { 37 _IsEndFlag = true; 38 } 39 } 40 if (string.IsNullOrEmpty(this._msg)) 41 { 42 context.Response.Write("timeout"); 43 } 44 else 45 { 46 context.Response.Write(this._msg); 47 } 48 } 49 catch (Exception ex) 50 { 51 string msg = ex.Message; 52 context.Response.Write("timeout"); 53 } 54 break; 55 case "ServiceReferenceB": try 56 { 57 ServiceReference2.OctorpusServiceClient _octorpusNO = new ServiceReference2.OctorpusServiceClient(); 58 this._msg = _octorpusNO.GetOctorpusNo(); 59 while (!_IsEndFlag) 60 { 61 62 if (!string.IsNullOrEmpty(this._msg)) 63 { 64 _IsEndFlag = true; 65 } 66 if (this._endTime <= DateTime.Now) 67 { 68 _IsEndFlag = true; 69 } 70 } 71 if (string.IsNullOrEmpty(this._msg)) 72 { 73 context.Response.Write("timeout"); 74 } 75 else 76 { 77 context.Response.Write(this._msg); 78 } 79 } 80 catch (Exception ex) 81 { 82 string msg = ex.Message; 83 context.Response.Write("timeout"); 84 } 85 break; 86 case "ServiceReferenceC": try 87 { 88 ServiceReference1.OctorpusServiceClient _octorpusNO = new ServiceReference1.OctorpusServiceClient(); 89 this._msg = _octorpusNO.GetOctorpusNo(); 90 while (!_IsEndFlag) 91 { 92 93 if (!string.IsNullOrEmpty(this._msg)) 94 { 95 _IsEndFlag = true; 96 } 97 if (this._endTime <= DateTime.Now) 98 { 99 _IsEndFlag = true; 100 } 101 } 102 if (string.IsNullOrEmpty(this._msg)) 103 { 104 context.Response.Write("timeout"); 105 } 106 else 107 { 108 context.Response.Write(this._msg); 109 } 110 } 111 catch (Exception ex) 112 { 113 //string msg = ex.Message; 114 context.Response.Write("timeout"); 115 } 116 break; 117 } 118 119 120 121 } 122 123 public bool IsReusable 124 { 125 get 126 { 127 return false; 128 } 129 } 130 } 131 }
最后还给大家来个小贴图把:
前段的;
简单说明下,这个B代表是个Recorder ,然后去请求客户端。页面的实现是采用Ajax异步传输的,这里就不在累赘了。我只是采用这种办法,解决了,这个问题,如果你有更好的办法,可以继续交流。谢谢!