夜鹰教程网-程序员的加油站
 当前位置:文章中心 >> Asp.net专题(WCF/WPF/WF)
搭一个简单的wcf服务
夜鹰教程网 来源:www.yyjcw.com 日期:2018-9-9 9:45:47
搭一个简单的wcf服务

之前在公司用的服务端是wcf写的,但是没有深入研究,最近找工作,面试的时候好多人看到这个总提问,这里做个复习


就用微软官方上的例子,搭一个简单的wcf服务,分6步


1 定义服务协定也就是契约,其实就是定义一个服务接口,这玩意后边是公开客户端用的,然后也告诉后边承载程序应该如何加载服务


   主要涉及两个特性:一个是ServiceContract(接口的特性,定义这个是服务契约,里边又一些设置参数可以设置一下),OperationContract设置接口的方法的,如果不设置,方法就不会呗公开


  这里是直接新建的wcf的服务程序,vs自动给生成了一个接口,就直接在这个里边添加了几个计算的接口函数了


复制代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Web;

using System.Text;


namespace GettingStartedLib

{


    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。

    //协定

    [ServiceContract(//CallbackContract =typeof(ICallBack),//双工时的返回协定

        ConfigurationName = "Calculator",//配置文件重的服务名

        Name = "ICalculator",//webservice描述文件重的portType名

        Namespace ="http://SampleWcfTest",//webservice描述文件重的portType命名空间

        ProtectionLevel =System.Net.Security.ProtectionLevel.EncryptAndSign,//保护等级

        SessionMode =SessionMode.Allowed)]//设置会话的支持模式

    public interface ICalculator

    {


        [OperationContract]

        string GetData(int value);


        [OperationContract]

        CompositeType GetDataUsingDataContract(CompositeType composite);

        //定义方法的操作,带了该特性才会被公布

        [OperationContract]

        double Add(double n1, double n2);

        [OperationContract]

        double Subtract(double n1, double n2);

        [OperationContract]

        double Multiply(double n1, double n2);

        [OperationContract]

        double Divide(double n1, double n2);


        // TODO: 在此添加您的服务操作

    }

    public interface ICallBack

    {

        [OperationContract(IsOneWay = true)]

        void Reply(string responseToGreeting);

    }


    // 使用下面示例中说明的数据约定将复合类型添加到服务操作。

    [DataContract]

    public class CompositeType

    {

        bool boolValue = true;

        string stringValue = "Hello ";


        [DataMember]

        public bool BoolValue

        {

            get { return boolValue; }

            set { boolValue = value; }

        }


        [DataMember]

        public string StringValue

        {

            get { return stringValue; }

            set { stringValue = value; }

        }

    }

}

复制代码

2 实现上边的接口,vs自动生成了svc文件和对应的svc.cs文件,直接双击就是对应的实现类了,吧接口实现就好了,这个svc文件右键用文本编辑器打开可以进行编辑,如果后边用IIS加载的时候需要修改里边的东西


复制代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Web;

using System.Text;


namespace GettingStartedLib

{

    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。

    // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。

    public class Calculator : ICalculator

    {

        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;

        }

        public double Add(double n1, double n2)

        {

            double result = n1 + n2;

            Console.WriteLine("Received Add({0},{1})", n1, n2);

            // Code added to write output to the console window.

            Console.WriteLine("Return: {0}", result);

            return result;

        }


        public double Subtract(double n1, double n2)

        {

            double result = n1 - n2;

            Console.WriteLine("Received Subtract({0},{1})", n1, n2);

            Console.WriteLine("Return: {0}", result);

            return result;

        }


        public double Multiply(double n1, double n2)

        {

            double result = n1 * n2;

            Console.WriteLine("Received Multiply({0},{1})", n1, n2);

            Console.WriteLine("Return: {0}", result);

            return result;

        }


        public double Divide(double n1, double n2)

        {

            double result = n1 / n2;

            Console.WriteLine("Received Divide({0},{1})", n1, n2);

            Console.WriteLine("Return: {0}", result);

            return result;

        }

    }

}

复制代码

3 承载服务,承载服务有几种方式,同时又设计到协议的绑定问题,


  绑定分类:BasicHttpBinding  最基础的http绑定,

        NetTcpbingding  TCP的  


        NetNamePipeBinding  IPC,也就是进程间通信,没用过。。


        WSHttpBinding  这个是特殊的http/Https协议 加了其他东西的


        NetMsmqBindiing,这个是消息队列,我没用过,这玩意好像需要额外装微软的消息队列才可以用


  这里我基本就用wshttpbinding来实现,


  承载方式:1)用控制台程序,直接用servicehost来承载服务,自己构造终结点:


复制代码

            //服务的地址

            Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");

            //承载服务的宿主

            ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress);


            try

            {

                selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");

                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();

                smb.HttpGetEnabled = true;

                selfHost.Description.Behaviors.Add(smb);

                selfHost.Open();

                Console.WriteLine("The service is ready.");

                Console.WriteLine("input<exit> to terminate service.");

                Console.WriteLine();

                while ("exit" == Console.ReadLine())

                {

                    selfHost.Close();

                }

            }

            catch (CommunicationException ex)

            {

                Console.WriteLine(ex.Message);

                selfHost.Abort();

                Console.ReadLine();

            }

复制代码

    2) 用IIS承载,这里又两种方式,通过internet的方式 这个可以直接在vs中调试的,选中svc文件点调试会弹出一个wcf的客户端测试程序,可以直接进行测试,但是这个客户端不能测试异步,只能测同步


    这中方式主要是需要配置一个web.config文件,部署的话,直接在IIS添加网站服务程序,把生成的DLL和web.config放在一个目录下应该跟这个调试是一样的(这种方式IIS5 6 只支持HTTP)


    还可以通过WAS(进程激活服务,支持的协议比上边多,这个就没有深入研究了···)


复制代码

<?xml version="1.0" encoding="utf-8"?>

<configuration>


  <appSettings>

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

  </appSettings>

  <system.web>

    <compilation debug="true" targetFramework="4.5.2" />

    <httpRuntime targetFramework="4.5.2"/>

  </system.web>

  <system.serviceModel>

    <services>

      <service name="GettingStartedLib.Calculator" behaviorConfiguration="MyServiceTypeBehaviors" >

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8001/"/>

          </baseAddresses>

        </host>

        <endpoint address="CalculatorService" binding="wsHttpBinding" contract="Calculator">

        </endpoint>

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="MyServiceTypeBehaviors" >

          <!-- 将下列元素添加到服务行为配置中。 -->

          <serviceMetadata httpGetEnabled="true" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

  <system.webServer>

    <!--<modules runAllManagedModulesForAllRequests="true"/>-->

    <!--

        若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。

        在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。

      -->

    <directoryBrowse enabled="true"/>

  </system.webServer>


</configuration>

复制代码

  3)通过windows服务程序承载,这个内部起始也是servicehost来实现,只不过是挂在windows服务程序上,需要自己实现一个windows服务,也就是继承servicebase类,重写onstart,在onstart中用servicehost加载服务,在stop中停止服务,同时需要配置文件就是程序的配置文件app.config记得生成到目录下,配置终结点。服务类生成的程序需要安装,还需要继承install实现一个安装类,把生成的服务程序安装到windows系统服务去,然后就可以在服务中启动服务,


这个安装是在管理员权限下进入对应的.netframework目录下运行installutil path(程序目录) 这里用的是4.5 ,就是v4.0。。


复制代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using GettingStartedLib;

using System.ServiceModel.Description;

using System.ServiceModel;

using System.ServiceProcess;

using System.Configuration.Install;

using System.ComponentModel;


namespace WcfConsole

{

    public class serviceCalss : ServiceBase

    {

        public ServiceHost serviceHost = null;

        public serviceCalss()

        {

            ServiceName = "WCFWindowsServiceSample";


        }

        protected override void OnStart(string[] args)

        {

            if (serviceHost != null)

            {

                serviceHost.Close();

            }

            serviceHost = new ServiceHost(typeof(Calculator));


            serviceHost.Open();

        }


        protected override void OnStop()

        {

            if (serviceHost != null)

            {

                serviceHost.Close();

                serviceHost = null;

            }

        }

    }

    class Program

    {

        static void Main(string[] args)

        {


            ServiceBase.Run(new serviceCalss());


            //服务的地址

            Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");

            //承载服务的宿主

            ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress);


            //try

            //{

            //    selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");

            //    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();

            //    smb.HttpGetEnabled = true;

            //    selfHost.Description.Behaviors.Add(smb);

            //    selfHost.Open();

            //    Console.WriteLine("The service is ready.");

            //    Console.WriteLine("input<exit> to terminate service.");

            //    Console.WriteLine();

            //    while ("exit" == Console.ReadLine())

            //    {

            //        selfHost.Close();

            //    }

            //}

            //catch (CommunicationException ex)

            //{

            //    Console.WriteLine(ex.Message);

            //    selfHost.Abort();

            //    Console.ReadLine();

            //}

        }

    }


    [RunInstaller(true)]

    public class ProjectInstaller : Installer

    {

        private ServiceProcessInstaller process;

        private ServiceInstaller service;


        public ProjectInstaller()

        {

            process = new ServiceProcessInstaller();

            process.Account = ServiceAccount.LocalSystem;

            service = new ServiceInstaller();

            service.ServiceName = "WCFWindowsServiceSample";

            Installers.Add(process);

            Installers.Add(service);

        }

    }

}

复制代码

对应的配置文件


复制代码

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <startup> 

        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />

    </startup>

  <system.serviceModel>

    <services>

      <!-- This section is optional with the new configuration model

           introduced in .NET Framework 4. -->

      <service name="GettingStartedLib.Calculator"

               behaviorConfiguration="CalculatorServiceBehavior">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8000/"/>

          </baseAddresses>

        </host>

        <endpoint address=""

                  binding="wsHttpBinding"

                  contract="Calculator" />

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="CalculatorServiceBehavior">

          <serviceMetadata httpGetEnabled="true"/>

          <serviceDebug includeExceptionDetailInFaults="False"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

复制代码

4 服务端承载好了,就可以用客户端调用服务了,又两种方式


  客户端直接引用已经运行的服务,vs会自动生成一个对应的client类,里边又设置好的服务路径和接口之类的,也可以自己指定路径,只用他的函数,记得close


复制代码

           // CalculatorClient client = new CalculatorClient();

            var client = myChannelFactory.CreateChannel();



            double value1 = 100.00D;

            double value2 = 15.99D;

            double result = client.Add(value1, value2);

            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

复制代码

  也可以用ChannelFactory<TChannel>类来构造一个client,这种模式是引用服务的契约接口,


     var myBinding = new WSHttpBinding();

            EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/GettingStarted/");

            //EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/"); 

            ChannelFactory<ICalculator> myChannelFactory = new ChannelFactory<ICalculator>(myBinding, myEndpoint);

  这里边都可以用配置文件来设置终结点,也就是绑定类型和地址,配置方式与服务端类似


5,6就是配置和调用,这里就不说了


这里只是简单的wcf实例,


实际还有内容没有涉及:


1 不同的绑定类型,怎么选择,网上有个图是判断什么情况选择对应的绑定类型,其实就是选择协议


2 加密,因为之间的程序用的是basichttpbingding就是就是基本的http绑定,客户端没用引用服务端,服务端以web服务的形式公开服务,客户端直接以http请求的形式来与服务端通信,这样客户端cs和bs可以公用一个服务端,但是没有加密,传输的内容是完全公开的··讲道理web服务这玩意本来就是发过去给人看的·公开应该也没啥好像····,面试的时候问到这个问题直接懵逼了···这里暂时没写 ··这玩意好像挺麻烦的···


3 这里在4.5的环境下编写的,服务公开以后会自动生成对应的异步执行方法,与之前的方式不同,之前是老式的beginxxx的异步方式,返回一个Iasyncresult的结果,这里是4.5的async/await的形式来执行异步操作


4 wcf服务是可以兼容asp.net ,也可以返回json格式的对象··这个可以通过设置方法的操作特性可以设置


5 wcf服务支持双工,这个就很流弊了,不过讲道理tcp这种本身就支持双工,没具体研究


6 在双工模式下支持回调,这个意思好像是客户端请求完成再出发一个回调服务么··· 没研究···


复制链接 网友评论 收藏本文 关闭此页
上一条: WCF简介  下一条: WCF配置说明
夜鹰教程网成立于2008年,目前已经运营了将近 13 年,发布了大量关于 html5/css3/C#/asp.net/java/python/nodejs/mongodb/sql server/android/javascript/mysql/mvc/easyui/vue/echarts原创教程。 我们一直都在坚持的是:认证负责、一丝不苟、以工匠的精神来打磨每一套教程,让读者感受到作者的用心。我们默默投入的时间,确保每一套教程都是一件作品,而不是呆板的文字和视频! 目前我们推出在线辅导班试运营,模式为一对一辅导,教学工具为QQ。我们的辅导学科包括 java 、android原生开发、webapp开发、商城开发、C#和asp.net开发,winform和物联网开发、web前端开发,但不仅限于此。 普通班针对的是国内学员,例如想打好基础的大学生、想转行的有志青年、想深入学习的程序员、想开发软件的初学者或者业余爱好者等。 就业办针对即将毕业上岗的大四学生,或者打算转行的初级开发工程师。 留学生班针对的是在欧美、加拿大、澳洲、日本、韩国、新加坡等地留学的中国学子,目的是让大家熟练地掌握编程技能,按时完成老师布置的作业,并能顺利地通过考试。 详细咨询QQ:1416759661   夜鹰教程网  基于角色的权限管理系统(c-s/b-s)。
  夜鹰教程网  基于nodejs的聊天室开发视频教程
  夜鹰教程网  Git分布式版本管理视频教程
  夜鹰教程网  MVC+EasyUI视频教程
  夜鹰教程网  在线考试系统视频教程
  夜鹰教程网  MongoDB视频教程。
  夜鹰教程网 Canvas视频教程
  夜鹰教程网 报表开发视频教程
  热点推荐
表单提交中get和post方式的区别有…
解决ASP中UTF-8与GB2312编码转换乱…
asp数组中REDIM的用法(动态数组)…
生成html的新方法ASP
ASP字符串函数大全
ASP生成Word文件的代码
ASP中Randomize随机函数的使用
十天学会ASP教程之第一天:安装调…
自定义的asp日期格式化函数
防范ASP网站漏洞的八大法则之一
十天学会ASP教程之第二天:表单传…
asp中关于从utf8页面到gb2312页面…
ASP教程:实现长文章分页功能
IIS6架设网站的问题总结
五分钟打开 allow_url_fopen 的最…
  最近更新
C# Json数据中的特殊字符导致页面…
博客园是有开发博客查询相关的接口…
C#里面的ref和out区别
C#调用API让声卡发出声音
.NET使用反射读取用户自定义的枚举…
.net操作SqlServer数据库增删改查…
如何将WCF服务部署到远程服务器
对WebApi 实现服务端信息的监控
用WCF生成Restful风格的接口返回 …
只有一个地址如何调用WCF服务
WCF简介
搭一个简单的wcf服务
WCF配置说明
WCF传输的数据量过大问题的解决方…
asp.net大文件分块上传文件秒传断…

关于我们 | 网站建设 | 技术辅导 | 常见问题 | 联系我们 | 友情链接

夜鹰教程网 版权所有 www.yyjcw.com All rights reserved 备案号:蜀ICP备08011740号3