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

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. python中的MRO和C3算法

    一. 经典类和新式类 1.python多继承 在继承关系中,python子类自动用友父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类 2.python2和python ...

  2. NOIP2013PUZZLE

    #include<cstdio> #include<cstring> #define MIN(A,B) (A)<(B)?(A):(B) using namespace s ...

  3. MVC框架入门准备(一)

    最近开发一套自己的框架,开发了一个多月,已传到git,学到了挺多,系列文章我会慢慢写挺多 这里先讲大致框架多用到的某些函数,我这里先列举一部分,网上对函数的定义,参数说明等,我就不照搬了,记录自己的理 ...

  4. 【OCP-12c】CUUG 071题库考试原题及答案解析(24)

    24. choose the best answer In the EMPLOYEES table there are 1000 rows and employees are working in t ...

  5. 任意模数NTT和FFT的玄学优化学习笔记

    本来一直都是写\(7\)次的\(MTT\)的--然后被\(shadowice\)巨巨调教了一通之后只好去学一下\(4\)次的了-- 简单来说就是我们现在需要处理一类模数不为\(NTT\)模数的情况 这 ...

  6. Ionic2 启动加载优化总结

    1. ionic2通过ionic serve生成的main.js大于4M,必须先build才能部署 npm run ionic:build --prod 之后main.js缩小为大概100K+ 2. ...

  7. Postgres中的SpinLock锁

    我们知道,在数据库中为了并发控制,少不了要使用各种各样的锁(lock).PostgreSQL中也不例外. 在PostgreSQL中有三种级别的锁,他们的关系如下: |上层 RegularLock | ...

  8. Python 字符串前面加u,r,b,f的含义

    1.字符串前加 u 例:u"我是含有中文字符组成的字符串." 作用: 后面字符串以 Unicode 格式 进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时 ...

  9. leetcode-482-License Key Formatting

    题目描述: You are given a license key represented as a string S which consists only alphanumeric charact ...

  10. C#-MVC-强数据类型、TempData、多表单、ajax

    一.强数据类型 将某一个或一组数据在控制器传递到视图上去 一个视图里只能有一个强类型数据 强类型数据 - 将某一个或一组数据在控制器传递到视图上去,同ViewBag,数据更稳定,防止多数据传递中出现错 ...