[转]WCF的几种寄宿方式
WCF寄宿方式是一种非常灵活的操作,可以在IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解。
1、 WCF服务的IIS服务寄宿
我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿。这种寄宿方式是最为方便的方式,而且由于服务只需要IIS运行就能自动运行起来,因此广为使用。
创建这种方式IIS寄宿方式的,只需要在解决方案里面,添加WCF服务应用程序,就可以生成这种的服务模块了。
这个是一个基于Web的应用程序,创建项目后会生成一个Service1.svc的服务页面,以及相关的WCF服务接口和实现,如下图所示。
这个就是简单的WCF服务,当然如果是复杂的实际应用,会考虑和数据库打交道,而且可能项目会分成几个进行管理,从而实现更好的逻辑分离操作。
2、 创建WCF服务库为多种寄宿做准备
除了上面常用的IIS服务寄宿,一般还会有各种各样的寄宿方式,不过如果采用其他方式的寄宿方式,一般会把WCF服务和寄宿方式进行项目的分离,实现更好的重用操作,特别WCF需要考虑多种寄宿方式的情况下。下面是WCF服务库和WCF服务应用程序的介绍说明,先了解一下基础。
WCF服务库,可以认为是一个包含WCF服务以及契约定义的类库。这里WCF服务库还不能直接运行,你可以在其他项目里引用,在宿主里启用托管这个库。
而WCF应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定义,可以直接看到运行的效果。此项目模板应该是基于IIS托管的程序。
前者一般考虑WCF服务设计的时候,服务类的定义为单独的库,可以为其它项目使用。提高代码的复用性。后者在开发基于IIS托管的WCF服务程序时,比较多见,自学的时候也可以使用这种类型。当然你也可以修改这些代码,比如把WCF服务程序里的类,移到一个单独的类库里。
创建WCF服务库,可以理解为我们开发.NET程序时创建的一个类库模块,不含界面,如下所示,创建一个WCF服务库。
确定后就只有一个示例服务Service1生成了。
这里,我们为了演示,就不修改任何它们的代码,原始的代码如下所示。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.Serialization;
- using System.ServiceModel;
- using System.Text;
- namespace WcfServiceLibrary
- {
- public class Service1 : IService1
- {
- public string GetData(int value)
- {
- return string.Format("You entered: {0}", value);
- }
- public CompositeType GetDataUsingDataContract(CompositeType composite)
- {
- if (composite == null)
- {
- throw new ArgumentNullException("composite");
- }
- if (composite.BoolValue)
- {
- composite.StringValue += "Suffix";
- }
- return composite;
- }
- }
- }

3、 WCF服务的控制台程序寄宿
这种也是一种常见的WCF服务寄宿方式,通过启动一个类似DOS窗口的控制台软件,实现WCF服务的动态寄宿,关闭控制台程序,服务就自然终止。
这种方式很简单,创建一个控制台程序,然后添加WCF服务类库的项目应用,在Main函数里面添加下面代码即可实现。

- namespace WcfService_HostConsole
- {
- class Program
- {
- static void Main(string[] args)
- {
- try
- {
- ServiceHost serviceHost = new ServiceHost(typeof(Service1));
- if (serviceHost.State != CommunicationState.Opened)
- {
- serviceHost.Open();
- }
- Console.WriteLine("WCF 服务正在运行......");
- Console.WriteLine("输入回车键 <ENTER> 退出WCF服务");
- Console.ReadLine();
- serviceHost.Close();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- }
- }
- }
- }

4、 WCF服务的Winform程序寄宿
和控制台程序一样,我们创建一个Winform项目,然后在窗体启动代码里面添加寄宿方式的代码即可,为了较好的响应体验,可以使用后台线程程序进行服务启动,如下所示。

- namespace WcfService_HostWinform
- {
- public partial class FrmMain : Form
- {
- ServiceHost serviceHost = null;
- BackgroundWorker worker = null;
- public FrmMain()
- {
- InitializeComponent();
- worker = new BackgroundWorker();
- worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
- worker.DoWork += new DoWorkEventHandler(worker_DoWork);
- if (!worker.IsBusy)
- {
- tssTips.Text = "正在启动......";
- lblTips.Text = tssTips.Text;
- worker.RunWorkerAsync();
- }
- }
- void worker_DoWork(object sender, DoWorkEventArgs e)
- {
- try
- {
- serviceHost = new ServiceHost(typeof(Service1));
- if (serviceHost.State != CommunicationState.Opened)
- {
- serviceHost.Open();
- }
- e.Result = "正常";
- }
- catch (Exception ex)
- {
- e.Result = ex.Message;
- }
- }
- void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- if (e.Result != null)
- {
- if (e.Result.ToString() == "正常")
- {
- tssTips.Text = "服务正在进行侦听......";
- }
- else
- {
- tssTips.Text = string.Format("错误:{0}", e.Result);
- }
- lblTips.Text = tssTips.Text;
- }
- }
- ...........................
- }
- }

当然为了防止Winform程序被不小心关闭,可以添加托盘代码,把程序缩小到托盘图标里面。
5、 WCF服务的Windows 服务程序寄宿
这种方式的服务寄宿,和IIS一样有一个一样的优点,系统启动后,WCF服务也会跟着启动了,不用人工干预,也是一种较好的寄宿方式。
为了实现这种方式的寄宿,我们创建一个控制台程序,然后添加响应的Window服务和安装程序类
然后在服务类启动里面添加WCF的寄宿代码,如下所示。

- public class ServiceManager : ServiceBase
- {
- private static object syncRoot = new Object();//同步锁
- private ServiceHost serviceHost = null; //寄宿服务对象
- public ServiceManager()
- {
- this.ServiceName = Constants.ServiceName;
- }
- /// <summary>
- /// 设置具体的操作,以便服务可以执行它的工作。
- /// </summary>
- protected override void OnStart(string[] args)
- {
- try
- {
- serviceHost = new ServiceHost(typeof(Service1));
- if (serviceHost.State != CommunicationState.Opened)
- {
- serviceHost.Open();
- }
- }
- catch (Exception ex)
- {
- LogTextHelper.Error(ex);
- }
- LogTextHelper.Info(Constants.ServiceName + DateTime.Now.ToShortTimeString() + "已成功调用了服务一次。");
- LogTextHelper.Info(Constants.ServiceName + "已成功启动。");
- }

为了实现通过该控制台程序实现参数化安装和卸载服务,我们需要拦截控制台的参数,并进行相应的操作,如下所示。

- /// <summary>
- /// 应用程序的主入口点。
- /// </summary>
- [STAThread]
- static void Main(string[] args)
- {
- ServiceController service = new ServiceController(Constants.ServiceName);
- // 运行服务
- if (args.Length == )
- {
- ServiceBase[] ServicesToRun;
- ServicesToRun = new ServiceBase[] { new ServiceManager() };
- ServiceBase.Run(ServicesToRun);
- }
- else if (args[].ToLower() == "/i" || args[].ToLower() == "-i")
- {
- #region 安装服务
- if (!ServiceIsExisted(Constants.ServiceName))
- {
- try
- {
- string[] cmdline = { };
- string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
- TransactedInstaller transactedInstaller = new TransactedInstaller();
- AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
- transactedInstaller.Installers.Add(assemblyInstaller);
- transactedInstaller.Install(new System.Collections.Hashtable());
- TimeSpan timeout = TimeSpan.FromMilliseconds( * );
- service.Start();
- service.WaitForStatus(ServiceControllerStatus.Running, timeout);
- }
- catch (Exception ex)
- {
- LogTextHelper.Info(ex);
- throw;
- }
- }
- #endregion
- }
- else if (args[].ToLower() == "/u" || args[].ToLower() == "-u")
- {
- #region 删除服务
- try
- {
- if (ServiceIsExisted(Constants.ServiceName))
- {
- string[] cmdline = { };
- string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
- TransactedInstaller transactedInstaller = new TransactedInstaller();
- AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline);
- transactedInstaller.Installers.Add(assemblyInstaller);
- transactedInstaller.Uninstall(null);
- }
- }
- catch (Exception ex)
- {
- LogTextHelper.Info(ex);
- throw;
- }
- #endregion
- }
- }

编译程序成功后,我们添加两个批处理的DOS脚本来实现执行程序的自动安装和卸载,如下所示。
安装脚本
- "WcfService_HostWinService.exe" -i
- pause
卸载脚本
- "WcfService_HostWinService.exe" -u
- pause
顺利执行脚本后,服务列表里面就增加一个服务项目了。
卸载操作,直接执行脚本就会卸载服务,非常方便哦。
6、 WCF服务的Web寄宿
当然,除了以上几种方式,这种以WCF服务库的方式,也可以在Web方式进行寄宿(IIS方式),这种方式更简单,添加一个后缀名的svc的文件,只需要一行代码即可,如下所示。
7、 使WCF服务支持GET方式调用
有时候,我们为了需要,可能通过一个小程序发布一个服务,然后供其他程序进行调用,可能是Web,也可以是Winform,但是我们是想提供一个基于HTTP,GET或者POST方式来实现接口的调用的,例如,提供一个JSON格式或者文本格式的内容返回操作。
如果是整合在Winform里面,那么我们在Winform里面添加一个WCF的项,修改里面的代码就可以了,如下所示。
首先要在使用GET方式的WCF服务接口的添加说明。如果是POS方式,增加设置有点不同([WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)])。

- namespace WcfServiceForWinform
- {
- [ServiceContract]
- public interface IService1
- {
- [OperationContract]
- void DoWork();
- [OperationContract]
- [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
- string GetData(int value);
- }
- }

第二,在实现类里面添加相应的设置

- namespace WcfServiceForWinform
- {
- [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
- public class Service1 : IService1
- {
- public void DoWork()
- {
- }
- public string GetData(int value)
- {
- return string.Format("You entered: {0}", value);
- }
- }
- }

配置文件如下所示,颜色标注特别的要注意:

- <?xml version="1.0"?>
- <configuration>
- <system.web>
- <compilation debug="true"/>
- </system.web>
- <system.serviceModel>
- <services>
- <service name="WcfServiceForWinform.Service1" behaviorConfiguration="ServiceConfig">
- <endpoint address="" binding="webHttpBinding"
- bindingConfiguration="webHttpBindingWithJsonP" behaviorConfiguration="webHttpBehavior"
- contract="WcfServiceForWinform.IService1">
- </endpoint>
- <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
- <host>
- <baseAddresses>
- <add baseAddress="http://localhost:9000/Service1/" />
- </baseAddresses>
- </host>
- </service>
- </services>
- <bindings>
- <webHttpBinding>
- <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
- </webHttpBinding>
- </bindings>
- <behaviors>
- <endpointBehaviors>
- <behavior name="webHttpBehavior">
- <webHttp/>
- </behavior>
- </endpointBehaviors>
- <serviceBehaviors>
- <behavior name="ServiceConfig">
- <serviceMetadata httpGetEnabled="True" policyVersion="Policy15"/>
- <serviceDebug includeExceptionDetailInFaults="False"/>
- </behavior>
- </serviceBehaviors>
- </behaviors>
- <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
- </system.serviceModel>
- <startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
- </startup>
- </configuration>

运行Winform程序,启动了WCF服务后,我们可以在浏览器(Chrome)上进行操作,如下结果所示。
从上图我们可以看到,这个通过Winform启动起来的WCF服务,连接也能通过GET方式进行接口调用了,接口可以通过参数进行传递,对于一些方便传输数据的接口如JSON接口,就是一种非常方便的调用了。
[转]WCF的几种寄宿方式的更多相关文章
- WCF开发框架形成之旅---WCF的几种寄宿方式
WCF开发框架形成之旅---WCF的几种寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者 ...
- (转)WCF开发框架形成之旅---WCF的几种寄宿方式
WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详 ...
- 微软 WCF的几种寄宿方式,寄宿IIS、寄宿winform、寄宿控制台、寄宿Windows服务
WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详 ...
- WCF学习之三, 寄宿方式 代码,配置文件
可以通过代码或者配置文件寄宿WCF服务,在使用过程中的一些心得,记录一下,方便后续查阅. 预备知识,几个地址的作用 1. behavior.HttpGetUrl 定义元数据的地址,如果不定义基地址, ...
- WCF - Hosting WCF Service 四种托管方式
https://www.tutorialspoint.com/wcf/wcf_hosting_service.htm After creating a WCF service, the next st ...
- WebApi 的三种寄宿方式 (二) - 宿主和控制器不在一个程序集
新建一个类库: SelfHost: 方法一: 1.添加对MyControllers类库的引用. 2.在控制台代码中加入一行代码: 当然,可以添加多个程序集.(记得引用) var config = ne ...
- WebApi 的三种寄宿方式 (一)
最近逛博客园,看到了Owin,学习了一下,做个笔记,说不定将来哪天就用上了 关于 Owin 的介绍,百度解释的很清楚了: https://baike.baidu.com/item/owin/28607 ...
- WCF寄宿方式
WCF开发框架形成之旅---WCF的几种寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者 ...
- WCF使用纯代码的方式进行服务寄宿
服务寄宿的目的是为了开启一个进程,为WCF服务提供一个运行的环境.通过为服务添加一个或者多个终结点,使之暴露给潜在的服务消费,服务消费者通过匹配的终结点对该服务进行调用,除去上面的两种寄宿方式,还可以 ...
随机推荐
- 2017北京国庆刷题Day1 morning T2
T2火柴棒 (stick) Time Limit:1000ms Memory Limit:128MB 题目描述 众所周知的是,火柴棒可以拼成各种各样的数字.具体可以看下图: 通过2根火柴棒可以拼出 ...
- 百度地图JavaScript API获取用户当前经纬度和详细地理位置,反之通过详细地理位置获取当前经纬度
前言: 前端时间刚好使用了百度地图的js api定位获取用户当前经纬度并获取当前详细位置和通过当前用户详细地理位置换取用户当前经纬度坐标的功能,为了方便下次找起来方便一些自己在这里记录一下,希望也能够 ...
- CSS-类和ID选择器的区别
学习了类选择器和ID选择器,我们会发现他们之间有很多的相似处,是不是两者可以通用呢?我们不要着急先来总结一下他们的相同点和不同点: 相同点:可以应用于任何元素不同点: 1.ID选择器只能在文档中使用一 ...
- python django简单操作
准备: pip3 install django==1.10.3 cmd django-admin startproject guest 创建一个guest的项目 cd guest manage. ...
- 355 Design Twitter 设计推特
设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近十条推文.你的设计需要支持以下的几个功能: postTweet(userI ...
- 深入理解async和await的作用及各种适用场景和用法
https://www.cnblogs.com/yaopengfei/archive/2018/07/02/9249390.html https://www.cnblogs.com/xianyudot ...
- Hadoop基础(一)
Hadoop 基础知识 大数据已经火了很长很长时间了,从最开始是个公司都说自己公司的数据量很大,我们在搞大数据.到现在大数据真的已经非常成熟并且已经在逐渐的影响我们的生产生活.你可能听过支付宝的金融大 ...
- fresh_bank、、
最近新学习了一个bank系统来和大家分享一下,新人求罩! 破索式之_链子枪_ 废话不多说了直接本主题 如果我们要写出bank系统,就要先考虑这个问题:总共需要几个类? 既然是银行系统,那么必不可少的就 ...
- Android基础TOP3_1:纵横屏切换
在Res下建立layout-port文件夹 为竖屏时加载的界面: 建立layout-land 文件夹 为横屏加载的界面
- 在PHP中调用php_ssh实现远程登陆linux服务器并执行shell脚本。
这个功能主要用于在web端利用程序对远程服务器进行操作,通过PHP_ssh执行shell脚本来实现. 首先要安装php_ssh2组件,linux中centos7下有ssh2源,直接安装.window下 ...