作为一个小菜鸟,为了纪念wcf学习的过程,偶尔写写几篇博客,在前人的基础上简化下,这样学起来更轻松些。我感觉这个错误契约貌似是在封装服务端的异常。为了不直接暴露服务端的错误,经过自定义处理。项目结构简单明了:
自定义错误契约
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace Service
{
/// <summary>
/// 用于记录错误信息
/// </summary>
[DataContract]
public class MathError
{
/// <summary>
/// 出错的操作
/// </summary>
private string _operation;
/// <summary>
/// 出错的信息
/// </summary>
private string _errorMessage;
public MathError(string operation, string errorMessage)
{
this._operation = operation;
this._errorMessage = errorMessage;
}
[DataMember]
public string Operation
{
get { return _operation; }
set { _operation = value; }
}
[DataMember]
public string ErrorMessage
{
get { return _errorMessage; }
set { _errorMessage = value; }
}
}
}
服务契约
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace Service
{
[ServiceContract]
public interface ICalculator
{
/// <summary>
/// 指定出现错误时返回的错误类型
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
[OperationContract]
[FaultContract(typeof(MathError))]
double Divide(double x, double y);
}
}
实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace Service
{
public class CalculatorService : ICalculator
{
#region ICalculator Members
public double Divide(double x, double y)
{
if (y == 0)
{
//throw new DivideByZeroException("除数不能为0");
MathError error = new MathError("Divide", "Divided by zero");
throw new FaultException<MathError>(error, new FaultReason("Parameters passed are not valid"), new FaultCode("sender"));
}
return x / y;
}
#endregion
}
}
服务寄宿:
using (ServiceHost calculatorHost = new ServiceHost(typeof(CalculatorService)))
{
calculatorHost.Opened += delegate
{
Console.WriteLine("启动服务:{0}", calculatorHost.BaseAddresses[0]);
};
calculatorHost.Open();
Console.Read();
}
服务配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- 部署服务库项目时,必须将配置文件的内容添加到
主机的 app.config 文件中。System.Configuration 不支持库的配置文件。 -->
<system.serviceModel>
<services>
<service name="Service.CalculatorService" behaviorConfiguration="calculatorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress = "http://192.168.10.2:8733/Service/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- 除非完全限定,否则地址相对于上面提供的基址-->
<endpoint
address="http://192.168.10.2:8733/Service/"
binding="basicHttpBinding"
contract="Service.ICalculator">
<!--
部署时,应删除或替换以下标识元素,以反映
在其下运行部署服务的标识。删除之后,WCF 将
自动推导相应标识。
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 -->
<!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除 -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="calculatorServiceBehavior">
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 要接收故障异常详细信息以进行调试,
请将以下值设置为 true。在部署前
设置为 false 可避免泄漏异常信息 -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
客户端引用:
using Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
namespace Client
{
class Program
{
static void Main(string[] args)
{
ChannelFactory<ICalculator> calculatorFactory = new ChannelFactory<ICalculator>("defualtEndpoint");
ICalculator calculator = calculatorFactory.CreateChannel();
try
{
Console.WriteLine("准备执行除法");
Console.WriteLine("x / y = {2} when x = {0} and y = {1}", 2, 0, calculator.Divide(2,0));
}
catch (FaultException<MathError> ex)
{
MathError error = ex.Detail;
Console.WriteLine("An Fault is thrown.\n\tFault code:{0}\n\tFault Reason:{1}\n\tOperation:{2}\n\tMessage:{3}", ex.Code, ex.Reason, error.Operation, error.ErrorMessage);
}
Console.Read();
}
}
}
客户端配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://192.168.10.2:8733/Service/"
binding="basicHttpBinding"
contract="Service.ICalculator"
name="defualtEndpoint" />
</client>
</system.serviceModel>
</configuration>
也可以下载源码