这几天公司需要做一个RESTFUL风格的服务接口,之前也没接触过,到网上找了一圈,发现WCF能够支撑,就试着弄了下,本以为半天就能搞定,结果做了两三天,里面的坑确实不少,现在总结一下,避免以后还犯类似错误。
记录以下几点:
1、POST以JSON入参注意事项;
2、设置路由方法;
3、如何改为https访问;
4、配置文件;
一、POST以JSON入参注意事项
先看下入参的Json格式
{"test_request_body": {"description": "This is a request body message."}}
数据分两层,外层是【test_request_body】,里层是【description】,那么对应的接口接收时,也应该将对象分为两层:
public class Test1
{
[JsonProperty("test_request_body")]
public TestModel test_request_body = new TestModel();
}
[DataContract]
public class TestModel
{
[DataMember]
public string description = string.Empty;
}
【TestModel】为里层信息,上面记得要加上“DataContract”,属性要加上“DataMember”,外层【Test1】里直接定义一个【TestModel】属性即可,这里要注意的是实例化对象的名称【test_request_body】,这个名必须和Json里的名称一致,否则接口无法解析Json数据,这个坑坑了我好久
下面是接口定义:
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "test_connection")]
string test_connection(Test1 test);
二、定义路由方法
添加全局类,然后在【Application_Start】方法中,添加下面信息:
System.Web.Routing.RouteTable.Routes.Add(new System.ServiceModel.Activation.ServiceRoute("onmc/v1/Test", new System.ServiceModel.Activation.WebServiceHostFactory(), typeof(Test)));
这样访问路径就会变成:http://localhost:12847/onmc/v1/Test/test_connection,符合RESTFUL风格
三、修改为https访问
第一步,需要生成证书,具体方式可按以下操作:
https://www.cnblogs.com/tangdacheng/p/4697175.html
第二步,导出证书,在浏览器上点击网址https左侧的小锁头,就能导出,主要在客户端请求时要使用
第三步,在IIS上配置https访问,记得先把第一步生成的证书导入到IIS所在服务中,否则配置时下拉看不到证书
第四步,设置Web.Config
如果要使用https访问,必须加上【secrity】节点,上面的配置里,【PatientService】和【LogService】使用了https访问方式
以上几步做完即可使用https访问
四、整体配置文件如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="MysqlConnString" value="server=127.0.0.1;database=ois_data;uid=root;port=3306;pwd=aaabbbccc;Charset=utf8;"/>
<add key="LogFilePath" value="F://DeviceLog//"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<!--文件上传大小设置-->
<binding name="myBindingTest">
</binding>
<binding name="myBindingPub">
</binding>
<binding name="myBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" transferMode="Streamed" >
<readerQuotas maxDepth="64" maxArrayLength="2147483647" maxStringContentLength="2147483647"/>
<!--https设置-->
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<!--定义服务-->
<services>
<service behaviorConfiguration="serviceBehavior" name="OisTransServer.PatientService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="myBinding" contract="OisTransServer.IPatientService" />
</service>
<service behaviorConfiguration="serviceBehavior" name="OisTransServer.LogService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="myBinding" contract="OisTransServer.ILogService" />
</service>
<service behaviorConfiguration="serviceBehavior" name="OisTransServer.PublicService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="myBindingPub" contract="OisTransServer.IPublicService" />
</service>
<service behaviorConfiguration="serviceBehavior" name="OisTransServer.Test">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="myBindingTest" contract="OisTransServer.ITest" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<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>
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning" propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="d:\wcf.svclog" />
</sharedListeners>
</system.diagnostics>
</configuration>
有以下两点需要说明:
1、所有的接口都需要在【services】中定义,【endpoint】可以空着不写;
2、【webHttpBinding】中,【myBinding】设置了Post数据大小,对应的是【PatientService】和【LogService】,这两个接口主要用于大量数据及文件传输;
最后,再说下实现方法中,常用到的功能
1、获取请求头信息
//用于获取请求头信息
IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
WebHeaderCollection headers = request.Headers;
str_transKey = headers["ACCESS_TOKEN"].ToString();
2、获取请求端信息
//用于获取访问端信息
OperationContext context = OperationContext.Current;
MessageProperties properties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
string str_reqAddress = endpoint.Address; //请求IP地址
string str_reqPort = endpoint.Port; //请求端口
3、设置httpStatus编码
//用于设置httpStatus
WebOperationContext woc = WebOperationContext.Current;
woc.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
//设置为400错误
woc.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.BadRequest;
4、返回标准的Json(不带【\"】转义符的)
//将对象result2转为Json字符串
string str_json = JsonConvert.SerializeObject(result2);
//设置返回Boday
HttpContext.Current.Response.ContentType = "application/json; charset=utf-8";
HttpContext.Current.Response.Write(str_json);