示例:WCF中Post、Get方式传递消息

一、目的:搭建利用windows服务,控制台为宿主的Post、Get服务,应用Json或字符串的方式进行参数传递

 

二、服务端搭建

 

1、定义实体

/// <summary>
    /// 消息实体
    /// </summary>
    public class MessageEntity
    {
        /// <summary>
        /// 消息
        /// </summary>
        public string message { get; set; }

        /// <summary>
        /// 消息类型
        /// </summary>
        public string type { get; set; }

        /// <summary>
        /// 优先级
        /// </summary>
        public string level { get; set; }
    }

    /// <summary>
    /// 返回消息
    /// </summary>
    public class ResultMessage
    {
        /// <summary>
        /// 消息代码
        /// </summary>
        public string Code { get; set; }

        /// <summary>
        /// 消息信息
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// 消息数据
        /// </summary>
        public string Data { get; set; }

        /// <summary>
        /// 创建消息
        /// </summary>
        /// <returns></returns>
        public static ResultMessage Create()
        {
            ResultMessage message = new ResultMessage();

            message.Code = "201";
            message.Data = DateTime.Now.ToString();
            message.Message = "调用成功";

            return message;
        }

2、定义服务接口

 /// <summary>
    /// WCF服务接口
    /// </summary>
    [ServiceContract]
    public interface IDataMessage
    {
        /// <summary>
        /// 测试Post消息
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "TestPost/{message}", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
        string TestPost(string message);

        //  Message:http://localhost:22889/Hello
        /// <summary>
        /// 测试Get消息
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        [WebGet(UriTemplate = "Hello", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        string TestGet();

        //  Message:1、"PostMessage?message={message}&type={type}&level={level}" 调用成功但是参数都为空
        //  Message:2、PostMessage?{message}&{type}&{level} 调用失败  格式必须为name=value
        //  Message:3、PostMessage?{message=message}&{type=type}&{level=level} 报错 格式无效
        //  Message:4、PostMessage?message={message}/type={type}/level={level} 报错 格式无效
        /// <summary>
        /// Post传递消息字符串
        /// </summary>
        /// <param name="message"></param>
        /// <param name="type"></param>
        /// <param name="level"></param>
        /// <returns></returns>
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "PostMessage?message={message}&type={type}&level={level}", ResponseFormat = WebMessageFormat.Json)]
        ResultMessage PostMessage(string message, string type, string level);

        /// <summary>
        /// Post方式传递实体
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        [OperationContract]
        [WebInvoke(Method = "POST",ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
        ResultMessage PostEntity(MessageEntity message);

        /// <summary>
        /// Post方式传递单一字符串
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "PostMMM/{message=message}/", BodyStyle = WebMessageBodyStyle.Bare)]
        string PostMMM(string message);

    }

3、实现服务接口

// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“DataMessage”。
    // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 DataMessage.svc 或 DataMessage.svc.cs,然后开始调试。
    public class DataMessage : IDataMessage
    {
        public ResultMessage PostEntity(MessageEntity message)
        {
            DataManager.Instance.Info("message:" + message.message);
            DataManager.Instance.Info("type:" + message.type);
            DataManager.Instance.Info("level:" + message.level);

            return ResultMessage.Create();
        }

        public ResultMessage PostMessage(string message, string type, string level)
        {
            DataManager.Instance.Info("message:" + message);
            DataManager.Instance.Info("type:" + type);
            DataManager.Instance.Info("level:" + level);

            //return DataManager.Instance.JsonResult();

            return ResultMessage.Create();

        }

        public string PostMMM(string message)
        {
            DataManager.Instance.Info("message:" + message);

            return "TRUE";
        }

        public string TestGet()
        {
            Console.WriteLine("TestGet成功");

            DataManager.Instance.Info("TestGet成功");

            return "TestGet成功";
        }

        public string TestPost(string message)
        {
            Console.WriteLine(message);

            DataManager.Instance.Info(message);

            return "成功";
        }
    }

4、WCF配置文件App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

  <!--WCF Start -->
  <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 behaviorConfiguration="GetPostBehavior" name="LTO.Repeater.Server.WCF.DataMessage.DataMessage">
        <endpoint address="" behaviorConfiguration="GetPostEndBehaviors" binding="webHttpBinding"
                  contract="LTO.Repeater.Base.Interface.IDataMessage">
        </endpoint>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

        <host>
          <baseAddresses>
            <add baseAddress="http://LocalHost:22889/"/>
            <!--<add baseAddress="http://LocalHost:54804/"/>-->
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <endpointBehaviors>
        <behavior name="GetPostEndBehaviors">
          <webHttp />
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>

        <behavior name="GetPostBehavior">
          <!--为避免泄漏元数据信息,请在部署前将以下值设置为 false-->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!--要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息-->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>

    <!--若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。-->
    <!--在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。-->

    <directoryBrowse enabled="true"/>
  </system.webServer>

  <!--WCF End -->
</configuration>

5、注册WCF服务

控制台宿主部分:

 class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Todo :初始化 
                DataManager.Instance.InitLogger();

                ServiceRegisterService.Instance.RegisterConfigDemo();

            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex);
            }

            System.Console.Read();

            System.Console.ReadKey();

        }
    }

Windows服务部分:

public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();

           
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                //Thread.Sleep(30000);

                string documentPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

                // Todo :初始化 
                DataManager.Instance.InitLogger();

                DataManager.Instance.Info("开始启动服务!");

                ServiceRegisterService.Instance.RegisterConfigDemo();

                DataManager.Instance.Info(documentPath);

                DataManager.Instance.Info("服务启动成功!");

            }
            catch (Exception ex)
            {
                DataManager.Instance.Info("服务启动错误!"); 
                DataManager.Instance.Error(ex);
            }
        }

        protected override void OnStop()
        {

            DataManager.Instance.Info("服务停止!");
        }
    }

ServiceRegisterService注册服务部分:

/// <summary> 注册服务 </summary>
    public class ServiceRegisterService
    {
        public static ServiceRegisterService Instance = new ServiceRegisterService();

        List<ServiceHost> _hosts = new List<ServiceHost>();


        public void RegisterConfigDemo()
        {
            this.RegisterWithConfig<Server.WCF.DataMessage.DataMessage>();
        }

        public void RegisterService<T>()
        {
            this.RegisterWithConfig<T>();
        }


        public void RegisterCodeDemo<T>()
        {
            this.RegisterWithCode<T>();
        }


        /// <summary> 用配置文件注册 (在配置文件中配置) </summary>
        public void RegisterWithConfig<T>()
        {
            try
            {
                ServiceHost host = new ServiceHost(typeof(T));

                host.Opened += (s, e) =>
                {
                    Log4Servcie.Instance.Info("WCF服务启动成功");
                };

                host.Open();
            }
            catch (Exception ex)
            {
                Log4Servcie.Instance.Info("WCF服务启动失败");
                Log4Servcie.Instance.Error(ex);
            }
        }

        /// <summary> 用代码注册(完全脱离配置文件) </summary>
        public void RegisterWithCode<T>()
        {
            try
            {
                Uri uri = new Uri("http://LocalHost:22999/");

                ServiceHost host = new ServiceHost(typeof(T), uri);

                // 要点一:定义元数据发布方式,此处  通过在服务所在的URL后加“?wsdl”的方式公布WSDL,可直接通过HTTP访问得到。
                System.ServiceModel.Description.ServiceMetadataBehavior behavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
                //此处没有定义mex终结点,必须设置HttpGetEnabled为true,否则客户端无法访问服务
                behavior.HttpGetEnabled = true;
                host.Description.Behaviors.Add(behavior);

                // 要点二:WebHttpBinding
                ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(T), new WebHttpBinding(), string.Empty);

                // 要点三:
                endpoint.EndpointBehaviors.Add(new WebHttpBehavior());

                //设置wcf支持ajax调用,仅适用于WebHttpBinding
                //System.ServiceModel.Description.WebScriptEnablingBehavior' is only intended for use with WebHttpBinding or similar bindings.
                //endpoint.Behaviors.Add(new WebScriptEnablingBehavior());

                host.Opened += (s, e) =>
                {
                    Log4Servcie.Instance.Info("WCF服务启动成功");
                };
                host.Open();

            }
            catch (Exception ex)
            {
                Log4Servcie.Instance.Info("WCF服务启动失败");
                Log4Servcie.Instance.Error(ex);
            }
        }

        public void CancelRegister()
        {
            foreach (var item in _hosts)
            {
                Log4Servcie.Instance.Info("Window服务停止成功");

                if (item != null)
                {
                    try
                    {
                        item.Close();
                        Log4Servcie.Instance.Info("WCF服务停止成功");
                    }
                    catch (Exception ex)
                    {
                        Log4Servcie.Instance.Info("WCF服务停止失败");
                        Log4Servcie.Instance.Error(ex);
                    }

                }
            }

        }

通过以上几步服务端接收Post和Get请求已经搭建完成

三、客户端调用

1、宿主启动:以管理员方式启动控制台程序或启动Windows服务

2、TestGet:

输入:

浏览器中:http://localhost:22889/Hello

Python:

r=requests.get('http://localhost:22889/Hello')
r.text

输出:"TestGet成功" 

3、TestPost:以Post方式传递的代码,PostMan、Python、C#等均可,本示例以Python方式演示

输入:

r=requests.post('http://localhost:22889/TestPost/sfd')
r.text

输出:

'"成功"'

4、PostMessage:以Post方式传递的代码,PostMan、Python、C#等均可,本示例以Python方式演示

输入:

r=requests.post('http://localhost:22889/PostMessage?message=你好&type=可以&level=还行')
r.text

输出:

'{"Code":"201","Data":"2019\\/1\\/7 19:51:17","Message":"调用成功"}'

5、PostEntity:以Post方式传递的代码,PostMan、Python、C#等均可,本示例以C#和PostMan方式演示

C#

 定义以Json方式传递的Post方法,如下

      /// <summary>
        /// 通过post上传
        /// </summary>
        public JContainer Post(string Url, string jsonParas)
        {
            try
            {
                string strURL = Url;
                HttpWebRequest request;
                request = (HttpWebRequest)WebRequest.Create(strURL);
                request.Method = "POST";
                request.ContentType = "application/json;charset=UTF-8";
                request.CookieContainer = cookieContainer;
                request.Timeout = 30000;
                string paraUrlCoded = jsonParas;
                byte[] payload;
                payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded);
                request.ContentLength = payload.Length;
                Stream writer = request.GetRequestStream();
                writer.Write(payload, 0, payload.Length);
                writer.Close();
                System.Net.HttpWebResponse response;
                response = (System.Net.HttpWebResponse)request.GetResponse();
                System.IO.Stream s;
                s = response.GetResponseStream();
                string StrDate = "";
                string strValue = "";
                StreamReader Reader = new StreamReader(s, Encoding.UTF8);
                while ((StrDate = Reader.ReadLine()) != null)
                {
                    strValue += StrDate + "\r\n";
                }
                return Newtonsoft.Json.JsonConvert.DeserializeObject(strValue) as Newtonsoft.Json.Linq.JContainer;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

单元测试如下:

   [TestMethod]
        public void TestMethod2()
        {
            NetWorkService netWorkService = new NetWorkService();

            MessageEntity messageEntity = new MessageEntity();
            messageEntity.message = "这是我的消息";
            messageEntity.level = "消息的优先级";
            messageEntity.type = "消息的类型";

            string json = JsonConvert.SerializeObject(messageEntity);

            var str = netWorkService.PostData("http://localhost:22889/PostEntity", json);

            Debug.WriteLine(str);

        }

服务端输出日志:

message:这是我的消息
type:消息的类型
level:消息的优先级

客户端返回结果:

'{"Code":"201","Data":"2019\\/1\\/7 19:51:17","Message":"调用成功"}'

PostMan:

在PostUrl中输入:http://localhost:22889/PostEntity

在Header中设置:Content-Type=text/json

在Body中设置row:{"message":"这是我的消息","type":"消息的类型","level":"消息的优先级"}

服务端输出日志:

message:这是我的消息
type:消息的类型
level:消息的优先级

客户端返回结果:

'{"Code":"201","Data":"2019\\/1\\/7 19:51:17","Message":"调用成功"}'

以上就是客户端调用的示例,本示例以Json和字符串方式传递参数,xml方式只需修改接口中定义

ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json即可

猜你喜欢

转载自blog.csdn.net/u010975589/article/details/86062619