客户端发送请求给服务端,服务端根据请求消息把消息转发给对应的终结点。这里面有个消息筛选机制,如果请求消息中带有地址报头相关信息,则会用地址报头匹配当前的所有终结点。所以默认情况下客户端和服务端的地址报头信息一致才可以正常通信。

AddressHeader地址报头是一个抽象类,并且没有构造方法。创建AddressHeader对象需要用到内部静态方法CreateAddressHeader。

public static AddressHeader CreateAddressHeader(string name, string ns, object value);

在WCF请求消息序列化后,AddressHeader也会被列化,其对应的XML节点描述为:值:name,命名空间:ns,结点名称:value。

下面是一个示例演示:

服务端代码:

using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
namespace hostAddressHeader
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(mywcf.CalculatorService)))
{
AddressHeader header1=AddressHeader.CreateAddressHeader("kk","www.kk.com","kkname");
EndpointAddress endpointaddress = new EndpointAddress(new Uri("http://localhost:8899"),header1);
ServiceEndpoint endpoint = new ServiceEndpoint(
ContractDescription.GetContract(typeof(mywcf.ICalculatorService)),
new WSHttpBinding(),
endpointaddress);
host.AddServiceEndpoint(endpoint);
host.Opened+=delegate{Console.WriteLine("Service Start!!");};
host.Open();
Console.ReadLine();
}
}
}
}

上述代码首先创建了一个AddressHeader对象,并将AddressHeader对象放入EndpointAddress。EndpointAddress可以有多个地址报头信息,这里只放入一个。

客户端代码:

using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
namespace clientAddressHeader
{
class Program
{
static void Main(string[] args)
{
AddressHeader header1=AddressHeader.CreateAddressHeader("kk","www.kk.com","kkname");
ServiceEndpoint endpoint=new ServiceEndpoint(
ContractDescription.GetContract(typeof(mywcf.ICalculatorService)),
new WSHttpBinding(),
new EndpointAddress(new Uri("http://localhost:8899"),header)
);
ChannelFactory<mywcf.ICalculatorService> factory=new ChannelFactory<mywcf.ICalculatorService>(endpoint);
mywcf.ICalculatorService client=factory.CreateChannel();
Console.WriteLine(client.Add(1, 2) + "");
}
}
}

客户端使用信道工厂进行创建信道,使用了与服务端相同的报头信息。服务端运行后,再运行客户端能正常访问。

客户端如果没有在EndpointAddress上指定报头,也可以通过OutgoingMessageHeaders直接在消息上添加报头信息。

 static void Main(string[] args)
{
AddressHeader header = AddressHeader.CreateAddressHeader("kk", "www.kk.com", "kkname");
mywcf.ICalculatorService client = ChannelFactory<mywcf.ICalculatorService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:8899"));
using (OperationContextScope scope = new OperationContextScope(client as IContextChannel))
{
OperationContext.Current.OutgoingMessageHeaders.Add(header.ToMessageHeader());
Console.WriteLine(client.Add(1, 2) + "");
}
}

若将客户端的报头地址改成如下:

  AddressHeader header1=AddressHeader.CreateAddressHeader("kd","www.kk.com","kkname");

会引发EndpointNotFoundException异常,因为服务端和客户端地址报头信息不一致,使用默认的消息筛选机制无法找到对应的终结点。

如果不想修改客户端地址报头,又想要避免这个错误,可以修改服务行为的消息筛选机制。筛选机制AddressFilterMode有3种,Exact,Predix,Any。

Exact是默认的筛选机制,要求客户端与服务端的地址报头精确匹配。Predix是前缀匹配,Any是任意匹配。将服务行为的AddressFilterMode 修改成任意匹配,即使客户端与服务端的地址报头不一致也可以访问了。AddressHeader与安全的作用不大,真正的作用是辅助寻址。因为客户端通过wsdl是可以获取到服务端完整的报头信息。

修改如下:

[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
public class CalculatorService : ICalculatorService {
  public int Add(int x, int y)   {
    return x + y;
  }
}

WCF中的AddressHeader作用的更多相关文章

  1. 在 WCF 中使用高效的 BinaryFormatter 序列化

    本文将定义一个 WCF 终结点行为扩展,以在 WCF 中使用更高效的 BinaryFormatter 进行二进制序列化,并实现对是否使用传统二进制序列化功能的可配置. 介绍 实现步骤 使用方法 效果 ...

  2. 游刃于MVC、WCF中的Autofac

    为了程序的健壮性.扩展性.可维护性,依赖抽象而不是具体实现类等等,于是我选择了Autofac依赖注入容器 就是这个工厂来降低耦合.之前买东西是自己去超市,现在呢 我需要什么东西,他们给送过来直接拿到了 ...

  3. 我的WCF之旅(3):在WCF中实现双工通信

    双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...

  4. WCF技术剖析之十一:异步操作在WCF中的应用(上篇)

    原文:WCF技术剖析之十一:异步操作在WCF中的应用(上篇) 按照操作执行所需的资源类型,我们可以将操作分为CPU绑定型(CPU Bound)操作和I/O绑定型(I/O Bound)操作.对于前者,操 ...

  5. [No0000126]SSL/TLS原理详解与WCF中的WS-Security

    SSL/TLS作为一种互联网安全加密技术 1. SSL/TLS概览 1.1 整体结构 SSL是一个介于HTTP协议与TCP之间的一个可选层,其位置大致如下: SSL:(Secure Socket La ...

  6. 在WCF中实现双工通信

    双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...

  7. WCF中的AsyncPattern

    WCF中的AsyncPattern   (系列博文源自 http://pfelix.wordpress.com/,由笔者翻译并整理,转载请注明) 在wcf 的 service contract中, 服 ...

  8. web.xml中load-on-startup的作用

    如下一段配置,熟悉DWR的再熟悉不过了:<servlet>   <servlet-name>dwr-invoker</servlet-name>   <ser ...

  9. WCF中,通过C#代码或App.config配置文件创建ServiceHost类

    C# static void Main(string[] args) { //创建宿主的基地址 Uri baseAddress = new Uri("http://localhost:808 ...

随机推荐

  1. 【cocos2d-x 手游研发小技巧(4)与Android混编实现换“头像图片”】

    cocos2dx在android平台上的游戏开发中往往会遇到一些混编需求,如: 比方有的社区类游戏需要用到更换玩家的“头像”操作,其实就是调用android servers服务里面的本地图片,以及选取 ...

  2. kvm快照备份及常用命令

    转载自:http://www.myjishu.com/?p=431 好文章 kvm快照备份及常用命令 kvm快照,分两种: 1种lvm快照,如果分区是lvm,可以利用lvm进行kvm的快照备份 2种由 ...

  3. JAVA Double去掉科学计数"E"

    当Double的值很大时,显示的结果会变成带E的科学计数法显示,在报表的数据显示的时候不方便阅读,需要去掉E,将原数据显示 public static void main(String[] args) ...

  4. item pipeline 实例:爬取360摄像图片

    生成项目 scrapy startproject image360 cd Image360 && scrapy genspider images  images.so.com 一. 构 ...

  5. C#-WebForm-★★★LinQ-数据的条件组合查询并进行分页展示(未加各种限定)★★★

    前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.as ...

  6. allure报告定制(pytest+jenkins)

    环境及安装可查看 pytest+jenkins安装+allure导出报告 要让allure报告更漂亮,更直观,需要在脚本中写入allure特性 一开始allure调用step().story().fe ...

  7. python 全栈开发:逻辑运算

    基础运算符 逻辑运算: 优先级:()> not > and >or 数字转bool值,0为False,非零的数字为True. 1. print(2 > 1 and 1 < ...

  8. Java NIO学习与记录(一):初识NIO

    初识 工作中有些地方用到了netty,netty是一个NIO框架,对于NIO却不是那么熟悉,这个系列的文章是我在学习NIO时的一个记录,也期待自己可以更好的掌握NIO. 一.NIO是什么? 非阻塞式I ...

  9. 总博客 wjyyy

    更多文章可见http://www.wjyyy.top/

  10. 2019.04.07 第三次训练 【WHU校赛】

    A: (模拟退火+点到线段最短距离) https://blog.csdn.net/Link_Ray/article/details/89173222 B:✅ C: (线段树+二分) https://b ...