第1章 wcf基础

什么是wcf: System.ServiceModel.dll

服务 服务的执行边界: proxy

地址:http/https,tcp,ipc,peer newwork,msmq,service bus(服务总线地址)

契约:服务契约,(类虽然可以使用内部的属性,索引器,静态成员,但WCF客户端却无法访问)

数据契约,错误契约,消息契约(不是WCF 的常见情况)

托管:iis托管只能使用http协议

was托管:(window激活服务)

wsa扩展程序(window server appfabric):主要面向的事wf服务

选择宿主:p21,22(互联网,局域网)

绑定:基本绑定,TCP绑定,IPC绑定,WEB服务绑定,MSMQ绑定

选择绑定:p24

终结点

元数据的交换:1.基于http-get的元数据,2.元数据交换终结点

客户端编程:生成代理

WCF体系结构: 不使用代理类,使用通道直接调用服务ChannelFactory

第2章 服务契约

操作重载:不同的name区分操作

契约继承

服务契约分解与设计:服务契约的最佳数量3-5个

第3章 数据契约

net格式器:1.BinaryFormatter 2.SoapFormatter

wcf格式器:DataContrct

第4章 实例管理

单调服务:percall 客户端持有一个代理的引用,不是实际的对象 (sessionmode.notallowed)

会话服务:persession (sessionmode.required)

单例服务:single 全局日志

限流

第5章 操作

请求应答操作,默认的操作模式

单向操作,没有返回值

回调操作(双向操作)

第6章 错误契约

错误契约,客户端捕捉

第7章 事务

第8章 并发管理

第9章 队列服务

第10章 安全

第11章 服务总线

中继服务

----------------------------------------------------------------------

WCF编码规范

一个全面完整的编码规范是成功交付产品的根本。规范有助于推行最佳实践以及避免缺陷,可以让团队成员更容易分享知识与技能。传统的编码规范是一本浩如烟海一般的高文大册,厚达数百页,详尽了每个指南的基本原理。制定这样的规范固然是有胜于无,然而,如此努力却很难被大多数开发者所接受。比较而言,本书介绍的WCF编码规范却只有薄薄的几篇,主要介绍了WCF编码细节、编码内容以及设计目的。我相信,若要充分理解各种编程决策,可能需要阅读大量书籍,积累数年的经验,然而如果要实施编码规范则不必如此。当吸收一名新兵加入你的团队时,你可以交给他这份规范,告诉他:“先看看这个。”若要完全理解以及认识到范围的价值,或许需要时间与经验,然而,如果只是需要在此之前就能够遵循规范的约定,却是一蹴而就的事情。编码规范详细介绍了编码要求、缺陷、指南以及建议。编码规范同时还使用了本书介绍最佳实践以及辅助类。

通用设计指南

  1. 所有的服务必须遵循以下原则:
    1. 服务是安全的。
    2. 服务操作在系统中应该保持状态一致。
    3. 服务是线程安全的,且可以被并发客户端访问。
    4. 服务是可靠的。
    5. 服务是健壮的。
  2. 服务应该遵循以下可选原则:
    1. 服务是可互操作的。
    2. 服务的规模是不变的。
    3. 服务是可用的。
    4. 服务是及时响应的。
    5. 服务是受限的,阻塞客户端的时间不能过长。

WCF基础

  1. 应该将服务代码放入到类库中,而不是放到宿主EXE中。
  2. 不要为服务类提供参数构造函数,除非托管的服务是明确的单例服务。
  3. 在相关的绑定中启用可靠性。
  4. 要为契约提供有意义的命名空间。对于公开向外的服务,可以使用公司的URL或者等同的URN,然后加上年份和月份以避免版本冲突;例如:

[ServiceContract(Namespace = "http://www.idesign.net/2009/06")]

interface IMyContract

{...}

对于局域网服务,可以使用任何有意义的唯一的名称,如MyApplication;例如:

[ServiceContract(Namespace = "MyApplication")]

interface IMyContract

{...}

  1. 对于运行在Windows XP以及Windows Server 2003 上的局域网应用程序,最好选用自托管,而不是IIS托管。
  2. 在Windows Vista和Windows Server 2008或更近版本中,最好选用WAS (IIS7)托管,而不是自托管。
  3. 启用元数据交换。
  4. 要为客户端配置文件中的所有终结点命名。
  5. 不要使用SvcUtil或者Visual Studio2008生成配置文件。
  6. 不要复制代理的代码。如果两个或多个客户端使用相同契约,可以将代理分解到单独的类库中。
  7. 总是关闭或释放代理。

服务契约

  1. 总是将ServiceContract特性应用到接口上,而不是类上:

//避免

[ServiceContract]

class MyService

{

[OperationContract]

public void MyMethod()

{...}

}

//正确

[ServiceContract]

interface IMyContract

{

[OperationContract]

void MyMethod();

}

class MyService : IMyContract

{

public void MyMethod()

{...}

}

  1. 服务契约要添加前缀I:

[ServiceContract]

interface IMyContract

{

[OperationContract]

void MyMethod();

}

  1. 要避免准属性(Property-Like)操作:

//避免

[ServiceContract]

interface IMyContract

{

[OperationContract]

string GetName();

[OperationContract]

void SetName(string name);

}

  1. 避免定义只有一个成员的契约。
  2. 每个服务契约最好只定义3~5个成员。
  3. 每个服务契约的成员不要超过20个。12个是可能的实际限定。

数据契约

  1. 避免推断式数据契约(POCO)。总是显式地应用DataContract特性。
  2. 只在属性或只读公有成员上使用Datamember特性。
  3. 避免为定制类型显式地执行XML序列化。
  4. 避免使用消息契约。
  5. 当使用DataMemberAttribute特性的Order属性时,应该为同一类层级的所有成员分配相同的值。
  6. 数据契约应实现IExtensibleDataObject接口。使用显式接口实现。
  7. 避免在ServiceBehavior和CallbackBehavior特性上设置IgnoreExtensionDataObject。应保持它的默认值为false。
  8. 不要将委托和事件标记为数据成员。
    1. 不要将.NET的特殊类型例如Type作为操作的参数。
    2. 不要在操作中接受或返回ADO.NET的DataSet类型和DataTable类型(或者它们的类型安全子类)。应该返回一个与技术无关的表示形式,例如数组。
    3. 禁止为泛型的类型参数生成散列值,而应该提供易懂的类型名。

实例管理

  1. 考虑系统的可伸缩性时,最好使用单调实例模式。
  2. 如果契约设置为SessionMode.NoAllowed,则总是将服务实例配置为InstanceContextMode.PerCall。
  3. 不要在相同的服务上混合使用会话契约与无会话契约。
  4. 避免使用单例服务,除非该服务本质上就是单例的。
  5. 要为会话服务使用有序递送。
  6. 避免为会话服务停止实例。
  7. 避免使用分步操作。
  8. 对于持久服务,总是指定完成操作。

操作与调用

  1. 不要将单向调用设置为异步调用。
  2. 不要将单向调用设置为并发调用。
  3. 对单向操作抛出的异常做出预期。
  4. 为单向调用启用可靠性。对于单向调用而言,使用有序传递属于可选项。
  5. 避免在会话服务中定义单向操作。如果定义了,则应将它定义为终止操作:

[ServiceContract(SessionMode = SessionMode.Required)]

interface IMyContract

{

[OperationContract]

void MyMethod1();

[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]

void MyMethod2();

}

  1. 为服务端的回调契约取名时,应使用服务契约名加上Callback后缀:

interface IMyContractCallback

{...}

[ServiceContract(CallbackContract = typeof(IMyContractCallback))]

interface IMyContract

{...}

  1. 尽量将回调操作标记为单向。
  2. 只为回调使用回调契约。
  3. 避免在相同的回调契约中将常规的回调与事件混为一谈
  4. 事件操作的设计应遵循如下规范:
    1. void返回类型
    2. 没有out参数
    3. 标记为单向操作
  5. 避免在事件管理中使用原来的回调契约,而应该使用发布-订阅框架
  6. 避免为回调显式地定义创建(Setup)方法和销毁(Teardown)方法:

[ServiceContract(CallbackContract = typeof(IMyContractCallback))]

Interface IMyContract

{

[OperationContract]

void DoSomething();

[OperationContract]

Void Connect();

[OperationContract]

void Disconnect();

}

Interface IMyContractCallback

{...}

  1. 使用类型安全的DuplexClientBase<T,C>,而不是DuplexClientBase<T>。
  2. 使用类型安全的DuplexChannelFactory<T,C>,而不是DuplexChannelFactory<T>。
  3. 调试或在局域网部署基于WSDualHttpBinding绑定的回调时,应该使用CallbackBaseAddressBehavior特性,并将CallbackPort设置为0:

[CallbackBaseAddressBehavior(CallbackPort = 0)]

Class MyClient:IMyContractCallback

{...}

错误

  1. 永远都不要在异常抛出之后使用代理实例,即使你捕获了该异常。
  2. 避免错误契约,并允许WCF屏蔽错误。
  3. 在异常抛出之后不要重用回调通道,即使你捕获了该异常,因为通道可能已经发生了错误。
  4. FaultContract特性中包含的类型应该是异常类类型,而不是单纯的可序列化类型:

//避免

[OperationContract]

[FaultContract(typeof(double))]

Double Divide(double number1,double number2);

//正确:

[OperationContract]

[FaultContract(typeof(DivideByZeroException))]

double Divide(double number1, double number2);

  1. 避免耗时过长的处理,例如IErrorHandler.ProvideFault()方法中的日志操作。
  2. 测试状态下,服务类与回调类的IncludeExceptionDetailInFaults值均应设置为true,可以在配置文件中配置,也可以采用编程方式:

public class DebugHelper

{

public const bool IncludeExceptionDetailInFaults =

#if DEBUG

true;

#else

false;

#endif

}

[ServiceBehavior(IncludeExceptionDetailInFaults =

DebugHelper.IncludeExceptionDetailInFaults)]

class MyService : IMyContract

{...}

  1. 构建交付版本时,除了诊断场景,不要将未知异常作为错误返回。
  2. 如果要提升异常为错误契约,并实现自动地错误日志记录,可以考虑在服务上使用ErrorHandlerBehavior特性:

[ErrorHandlerBehavior]

class MyService : IMyContract

{...}

  1. 如果要提升异常为错误契约,并实现自动地错误日志记录,可以考虑在回调客户端上使用CallbackErrorHandlerBehaviorAttribute特性:

[CallbackErrorHandlerBehaviorAttribute]

class MyClient : IMyContractCallback

{

public void OnCallback()

{...}

}

事务

  1. 永远不要直接使用ADO.NET事务。
  2. 要将TransactionFlow特性应用在契约上,而不是服务类上。
  3. 不要再服务构造函数中执行事务型工作。
  4. 如果使用本书术语,服务应该被配置为Client事务或Client/Service事务。避免使用None事务或Service事务。
  5. 如果使用本书术语,回调应该被配置为Service事务或Service/Client事务。避免使用None事物或Callback事物。
  6. 使用Client/Service或Service/Callback模式时,应该使用BindingzRequirement特性约束绑定使用事务流。
  7. 如果服务被配置为None事务或Service事务,则客户端总是会捕获它所抛出来的异常。
  8. 在使用事务时,允许可靠性和有序传递。
  9. 在服务操作中,永远不要捕获一个异常,并手动取消事务。

//避免

[OperationBehavior(TransactionScopeRequired = true)]

public void MyMethod()

{

try

{

...

}

catch

{

rtansaction.Current.Rollback();

}

}

  1. 如果在事务型操作中捕获了一个异常,那么总是要重新抛出它,或者抛出其它异常。
  2. 保证事务尽可能短。
  3. 总是使用默认的隔离级别IsolationLevel.Serializable。
  4. 不要调用事务中的单向操作。
  5. 不要调用事务中的非事务型服务。
  6. 不要访问事务中的非事务型资源(例如文件系统)。
  7. 对于会话服务,避免在会话关闭时通过自动完成将会话边界与事务边界等同对待。
  8. 尽量使用TransationalBehavior特性管理会话服务的事务。

[Serializable]

[TransationalBehavior]

class MyService :IMyContrant

{

public void MyMethod()

{...}

}

  1. 使用一个会话服务后事务型的单例服务时,应使用易失性资源管理器管理状态,同事避免显示的状态相关的编程,或者在完成时依赖WCF停止实例。
  2. 对于事务性持久服务,总是将SaveStateInOperationTransaction设置为true,从而将事务传播给持久存储。

并发管理

  1. 总是线程安全访问如下内容:
    1. 会话服务或单例服务的内存状态
    2. 回调期间的客户端内存状态
    3. 共享资源
    4. 静态变量
    5. 建议选用ConcurrencyMode.Single(默认值)。它能够启用事务型访问,并提供线程安全的。
    6. 在ConcurrencyMode.Single模式下,保证会话服务和单例服务的操作耗时短,这是为了避免过长时间地堵塞其他客户端。
    7. 使用ConcurrencyMode.Multiple时,必须使用自动完成事务。
    8. 考虑为单调服务使用ConcurrencyMode.Multiple,从而允许并发调用。
    9. 配置为ConcurrencyMode.Multiple的事务型单例服务,则必须将ReleaseServiceInstanceOnTransactionComplete设置为false:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,

ConcurrencyMode = ConcurrencyMode.Multiple,

ReleaseServiceInstanceOnTransactionComplete = false)]

class MySingleton : IMyContract

{...}

  1. 永远不要在UI线程上实现自托管,也不要通过UI应用程序调用服务。
  2. 永远不要执行到达调用服务的UI应用程序的回调,除非回调使用SynchronizationContext.Post()方法传递调用。
  3. 为同步方法和异步方法提供代理时,只能将FaultContractAttribute特性应用到同步方法上。
  4. 保证异步操作尽可能短。不要将异步操作与长时间操作混为一谈。
  5. 不要混合使用事务与异步调用

队列服务

  1. 在客户端,总是调用队列服务之前验证队列(如果可能则验证死信队列)是否可用。可以使用QueuedServiceHelper.VerifyQueue()方法进行验证。
  2. 在运行一个队列服务(通过ServiceHost<T>自动执行)时,总是要验证队列是否可用。
  3. 除了是在隔离场景中,要避免设计相同的服务同时工作在队列和非队列中。
  4. 服务应该参与回放事务。
  5. 参与回放事务时,要避免在队列服务中执行耗时过长的处理。
  6. 避免会话队列服务。
  7. 使用一个单例队列服务时,应使用易失性资源管理器管理单例状态。
  8. 使用一个单调队列服务时,要显式地将契约和服务配置为单调模式以及无会话状态:

[ServiceConstract(SessionMode = SessionMode.NotAllowed)]

interface IMyContract

{...}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

class MyService : IMyContract

{...}

  1. 总是将单例队列服务的契约显式地设置为禁止会话:

[ServiceConstract(SessionMode = SessionMode.NotAllowed)]

interface IMyContract

{...}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

class MyService : IMyContract

{...}

  1. 客户端应该在事务内调用一个队列服务。
  2. 在客户端,不要将队列服务代理储存在成员变量中。
  3. 避免将TimeToLive的值设置为相对较短的值,因为他们会抵消使用队列服务的价值。
  4. 避免非事务队列。
  5. 使用响应队列时,要让服务参与到回放事务中,并在事务中将响应放入队列。
  6. 要让响应服务参与到响应回放事务中。
  7. 避免在一个队列响应操作中执行耗时过长的处理。
  8. 对于MSMQ3.0 建议使用一个响应服务,而不是有害队列服务去处理服务自身的重复错误。
  9. 对于 MSMQ4.0 应对有害消息使用ReceiveErrorHandling.Reject, 除非通过ReceiveErrorHandling.Move 进行高级处理。应避免ReceiveErrorHandling.Fault和ReceiveErrorHandling.Drop。
  10. 对于 MSMQ4.0 考虑使用响应服务来处理服务回放失败。
  11. 除非是处理一个会话契约与会话服务,否则永远不要假定队列调用的顺序。

安全

  1. 总是要保护消息,提供消息证书与完整性。
  2. 在局域网中,只要保护级别被设置为EncryptAndSign,就可以使用传输安全。
  3. 在局域网中要避免使用模拟。应将模拟级别设置为TokenImpersonationLevel.Identification.
  4. 当使用模拟时,客户端应使用TokenImpersonaltionLevel.ImPersonation。
  5. 应使用声明性安全框架,避免手动配置。
  6. 永远不要将PrincipalPermission特性直接应用到服务类上:

//总是会失败

[PrincipalPermisson (SecurityAction.Demand,Role = “…”) ]

public calss MyService : IMyContract

{...}

  1. 避免在服务构造函数中使用需要授权的敏感工作。
  2. 不管是否要求角色,都应该避免强制要求一个特定的用户:

//避免

[[PrincipalPermisson (SecurityAction.Demand,Role =”John”) ]

public void MyService : IMyMethod

{...}

  1. 在客户端的回调操作中不要依赖于基于角色的安全机制。
  2. 对于互联网客户端,总是要使用消息安全。
  3. 允许客户端与服务证书进行协商(默认)。
  4. 使用ASP.NET的Provider定制证书。
  5. 开发一个定制证书存储时,应将它开发为ASP.NET Provider.
  6. 在使用端点信任( Peer Trust )时要验证证书。
  7. 尽量将客户端运行在部分信任之下。只能将客户端许可授予:
    1. 执行
    2. 显示用户界面
    3. 连接服务
    4. 获得本地凭据
  8. 在获得服务宿主环境时,在完全信任下运行和托管。将Microsoft和ECMA授予完全信任,但要移除其他的代码组,并将他们授予无许可权。
  9. 在部分信任下托管,只能将宿主和服务许可授予为:
    1. 执行
    2. 接受客户端调用
    3. 获得本地凭据
    4. 认证和授权客户端
    5. 如果需要获得本地资源

 

wcf服务编程(第3版)文摘的更多相关文章

  1. 《WCF服务编程第三版》知识点摘录

  2. WCF服务编程

    WCF服务编程, 我是WCF的初学者,在这想分享学习WCF服务编程的过程,欢迎大家多多指教!

  3. WCF服务编程 读书笔记——第2章 服务契约

    操作重载诸如 C++ 和 C# 等编程语言都支持方法重载,即允许具有相同名称的两个方法可以定义不同的参数.例如,如下的 C# 接口就是有效的定义: interface ICalculator { in ...

  4. WCF服务编程 读书笔记——第1章 WCF基础(2)

    续:第1章 WCF基础(1) 元数据交换 服务有两种方案可以发布自己的元数据.一种是基于HTTP-GET协议提供元数据, 另一种则是后面将要讨论的使用专门的终结点的方式.WCF能够为服务自动提供基于H ...

  5. WCF服务编程 读书笔记——第1章 WCF基础(1)

    第1章 WCF基础 本章主要介绍WCF的基本概念.构建模块以及WCF体系架构,以指导读者构建一个简单的WCF服务.从本章的内容中,我们可以了解到WCF的基本术语,包括地址(Address).绑定(Bi ...

  6. WCF服务编程-基础

    WCF是微软建立新一代的分布式应用及面向服务应用的标准平台,是基于原有.NET Framework 2.0的扩展.虽然在WCF发布不久就已经在项目中使用WCF技术了.但是由于在项目中还没有较大规模的应 ...

  7. WCF 服务编程 - 常用绑定

    WCF  定义了5中常用的绑定. 一. 绑定 1.基本绑定: 对应于BasicHttpBinding类.基本绑定能够将WCF服务公开为传统的ASMX Web服务,使得原客户端能够与新的服务协作.如果客 ...

  8. WCF服务编程中使用SvcMap实现类型共享等技巧【转】

    原文链接:http://www.cr173.com/html/19026_1.html 国外的一篇文章:Sharing DataContracts between WCF Services 文中提到的 ...

  9. 检测WCF服务是否在线第二版

    上一版在这里http://www.cnblogs.com/kklldog/p/4878296.html 上一版主要是解决了监控服务不需要手动添加服务引用的问题,但是还是需要在配置文件中添加对应的end ...

随机推荐

  1. Django ORM介绍 和字段及字段参数

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

  2. linux下配置python环境 django创建helloworld项目

    linux下配置python环境 1.linux下安装python3 a. 准备编译环境(环境如果不对的话,可能遇到各种问题,比如wget无法下载https链接的文件) yum groupinstal ...

  3. 什么是HBase(二) 关于HFile分割

    关于HFile的分割,是首先要从HFile的合并说起,上回书讲到memstore会不定期刷HFile,然后这些HFile将会被不定过期的被监控程序进行小合并+大合并(所有的文件,不分column fa ...

  4. 判断网络类(获取mac) InternetCheck

    using System; using System.Collections.Generic; using System.Net.NetworkInformation; using System.Ru ...

  5. js基础篇string&&array(应YX同学面试复习要求 - -)

    js中的数据类型一共有五个基本数据类型,分别是undefined,null,boolean,number,string. js中的Object类型中包括两大类型:Function类型和array类型. ...

  6. ipython的使用

    改初始路径 还有一个坑,可以用notebook打开一个已经存在的文件,但是不能正常编辑(使用单元编辑),因为使用这个创建的东西根本就不是一个.py文件,如果代码编辑完毕,倒是可以通过下载那里选择下载成 ...

  7. Centos生成SSL证书的步骤

    1.yum install openssl安装openssl组件2.生成KEY的流程步骤如下 1. 创建根证书密钥文件(自己做CA)root.key: openssl genrsa -out root ...

  8. tensorflow-windows下安装,python3.6

    安装: pip install tensorflow ps:我第一次安装了,但是导入却失败了. 进入\python3\Lib\site-packages\删除了tensorflow,再次pip ins ...

  9. Selenium Webdriver——去哪儿网输入实例

    1.对出发地方和到达地方进行Xpath定位,这里采用了Xpath的text() 函数进行定位 用following::sibling选择当前元素后的兄弟元素,比如出发框的Xpath表达式如下: .// ...

  10. Java各种Utils小结

    原文地址:http://trinea.iteye.com/blog/1533616 最新内容建议直接访问原文:Android常用的工具类 主要介绍总结的Android开发中常用的工具类,大部分同样适用 ...