一、目的:搭建利用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即可