基本步骤
- 定义传输数据类型
- 定义请求契约
- 网络访问的接口URL
- Controller的方法接口
- 实现网络请求接口
- 定义配置文件
- 申明服务(ABC三要素)
- 申明行为约束
- 申明服务器端参数(支持Jsonp方式访问异步数据)
- 将契约接口注册到控制台中
定义传输数据类型
基本说明
- 传输数据类型,实质是一个受到特性限制的pojo/Vo/DAO类
- 传输数据类型,会依据不同的配置参数,在传递过程中序列化为Json或者xml两种交换格式
- 传输数据类型,其正反序列化都是由.NET框架自动进行
实例代码
namespace WCF_DataReaderService
{
[DataContract]
public class ResultEntry
{
private bool state;
private string message;
private string value;
[DataMember]
public bool State
{
get { return state; }
set { state = value; }
}
[DataMember]
public string Message
{
get { return message; }
set { message = value; }
}
[DataMember]
public string Value
{
get { return value; }
set { this.value = value; }
}
}
}
代码代码说明
- 特性 DataContract 限定当前实体类为传输数据类型
- 特性 DataMember 限定当前属性需要被执行正反序列化
定义请求契约
基本说明
- 请求契约在物理上就是一个受到特性限制的Interface
- 请求契约对外确定了当前网络请求的具体URL,请求方式和返回结果类型
- 请求契约对内确定了要相应请求的功能类的方法名称和参数类型
实例代码
namespace WCF_DataReaderService
{
[ServiceContract]
public interface IDataReaderService
{
[OperationContract]
[WebInvoke(
Method = "GET",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "ReadFile/FileName={value}"
)]
ResultEntry ReadFile(string value);
[OperationContract]
[WebInvoke(
Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "ConnectTest"
)]
ResultEntry ConnectTest();
}
}
代码说明
- 特性 ServiceContract 限定当前接口为请求契约
- 特性 OperationContract 限定当前方法为契约执行方法接口
- 特性 WebInvoke 限定当前方法的对外的网络请求参数,包括URL,支持请求方式以及响应结果类型
- 返回类型 ResultEntry 为自定义参数类型,在当前配置模式下,返回的结果Entry实体会自动被序列化成为json字符串
实现业务逻辑
基本说明
- 该过程实际就是实现契约接口
- 请求契约中各个方法相互独立,不能在契约方法A中调用契约方法B
- 依据MVC架构,契约实体类中不包含任具体业务逻辑,只是将调用Service层中的方法
实例代码
namespace WCF_DataReaderService
{
public class DataReaderService : IDataReaderService
{
public ResultEntry ReadFile(string value)
{
ResultEntry result = ResultEntry.CreateSuccessEntry("");
JsonDataFileController controller = new JsonDataFileController();
if (controller.IsFileExist(value) == false)
return result.UpdateState(false, controller.DisplayError_FileNotExsit(value));
if (controller.ReadFileValue(value) == false)
return result.UpdateState(false, controller.DisplayError_FileReadError(value));
result.UpdateResult(controller.Result);
controller.Release();
return result;
}
public ResultEntry ConnectTest()
{
ResultEntry result = ResultEntry.CreateSuccessEntry("this is test");
return result;
}
}
}
代码说明
- ReadFile 方法用于读取指定目录下,由参数指定的文件名内容,并将读取内容写到ResultEntry的Value属性中
- ConnectTest 方法用于测试网络连接是畅通,无任何有意义的业务逻辑
- JsonDataFileController 封装了具体的文件内容读取实现过程,具体代码如下所示
namespace WCF_DataReaderService.Controller
{
public class JsonDataFileController
{
public bool IsFileExist(string value)
{
DataFileFoldConfig config = DataFileFoldConfig.Load();
return (File.Exists(config.BaseFold + "/" + value));
}
public bool ReadFileValue(string value)
{
bool result = false;
try
{
DataFileFoldConfig config = DataFileFoldConfig.Load();
string FileName = config.BaseFold + "/" + value;
using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
using (StreamReader sw = new StreamReader(fs, Encoding.UTF8))
{
Result = sw.ReadToEnd();
}
}
result = true;
}
catch (Exception ex)
{
Console.WriteLine("ReadFileValue {0} ", ex.Message);
}
return result;
}
public string DisplayError_FileNotExsit(string value)
{
DataFileFoldConfig config = DataFileFoldConfig.Load();
string FileName = config.BaseFold + "/" + value;
return string.Format("文件{0}不存在", FileName);
}
public string DisplayError_FileReadError(string value)
{
DataFileFoldConfig config = DataFileFoldConfig.Load();
string FileName = config.BaseFold + "/" + value;
return string.Format("文件{0} 读取错误", FileName);
}
public string Result { get; set; }
public void Release()
{
Result = "";
}
}
}
定义配置文件
- 配置文件实际就是宿主项目的App.config文件
实例代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
<services>
<service behaviorConfiguration="WCF_DataReaderService.Behavior(服务行为名)" name="WCF_DataReaderService.DataReaderService(契约实现类全称)">
<endpoint address="http://127.0.0.1:3721/CSQData(网络请求基础路径)" kind="webHttpEndpoint" contract="WCF_DataReaderService.IDataReaderService(请求契约接口类全称)" behaviorConfiguration="WCF_DataReaderService.RestfulBehavior(端口行为配置名)"></endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WCF_DataReaderService.RestfulBehavior(端口行为配置名)">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WCF_DataReaderService.Behavior(服务行为名)">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET" />
<add name="Access-Control-Allow-Headers" value="x-requested-with,content-type" />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
代码说明
- 一般情况下 services节点和behaviors节点,需要依据实际的请求契约接口名进行修改并确保相互配套
- 一般情况下 其他节点内容,可以不修改直接使用
将契约接口注册到控制台中
基本说明
- 实际就是启动一个无限循环的控制台,实现网络请求的持续监听,充当服务器
- 该控制台程序所在项目需要特别引入如下dll支持
- System.ServiceModel
- System.ServiceModel.Web
- System.Web.Services
- System.Web
实例代码
namespace WCF_Host
{
class Program
{
static void Main(string[] args)
{
using (WebServiceHost host = new WebServiceHost(typeof(DataReaderService)))
{
try
{
host.Open();
Console.WriteLine("服务已经启动,输入exit退出...");
while (true)
{
string temp = Console.ReadLine();
if (temp.Equals("exit", StringComparison.CurrentCultureIgnoreCase))
{
break;
}
}
host.Close();
}
catch (Exception ex)
{
Console.WriteLine("服务启动异常{0},输入exit退出...", ex.Message);
}
}
}
}
}
代码说明
- 请求契约实现类,实际通过WebServiceHost对象,注入到控制台容器中
- 控制台通过监听输入值是否为“exit”,判断是否需要执行退出
网页请求Js代码
- 该请求过程采用JQuery的jsonp技术
function JQuery_ConnectTest()
{
$.ajax
({
async: false,
crossDomain: true,
type: "get",
url: "http://127.0.0.1:3721/CSQData/ConnectTest",
dataType: 'jsonp',
success: function(data)
{
console.log(0,data);
$("p").text(JSON.stringify(data));
},
error: function(xhr, type)
{
console.log(0,xhr);
}
});
}
function JQuery_ReadFile(filePath)
{
$.ajax
({
async: false,
crossDomain: true,
type: "get",
url: "http://127.0.0.1:3721/CSQData/ReadFile/FileName=" + filePath,
dataType: 'jsonp',
success: function(data)
{
result = JSON.stringify(data);
$("p").text(result);
JQuery_ReadFile_Post(result);
},
error: function(xhr, type)
{
console.log(0,xhr);
}
});
}