参考了蒋金楠老师08年的文章。好吧,那时候我才大二、大三,大神果然是大神。 http://www.cnblogs.com/artech/archive/2008/09/01/1280939.html

在使用AX2012 AIF服务的时候,有一个问题一直困扰着我,那就是访问权限的认证。

众所周知AX2012的权限认证是基于AD的,但有些客户端机器的AD账户,并没有AX2012的访问权限,甚至没有加入AD中(如PDA客户端)。

按照微软的最佳实践,应该使用声明账户和可信中介这样两样技术,来实现客户端-》WCF中间层(可信中介)-》AIF服务。这样做好处,是客户端不用加入AD中,并且可以将客户端登陆账户权限的管理,纳入到AX中。

如果使用AX2012的自定义服务,会在AOS中有多个数据契约和服务操作,如果一个一个再在WCF中间层去重复造轮子,有些麻烦。能不能将中间层进行简化成,只是将客户端请求转发给AIF,将AIF的响应返回给客户端呢?

答案肯定是可以的咯,不然我也不会写这篇文章。具体可以参考上面蒋金楠老师博文的链接。

1新建一个WCF类库程序,代码如下:

namespace MessageInterceptor

{

[ServiceContract]

public interface IIntercept

{

[OperationContract(Action ="*", ReplyAction="*")]

Message Intercept(Message request);

}

[ServiceBehavior(UseSynchronizationContext = false, AddressFilterMode = AddressFilterMode.Any)]

public class InterceptService : IIntercept

{

public System.ServiceModel.Channels.Message Intercept(System.ServiceModel.Channels.Message request)

{


using (ChannelFactory<IIntercept> channelFactory = new
ChannelFactory<IIntercept>("calculateService"))

{

IIntercept interceptor = channelFactory.CreateChannel();

using (interceptor as IDisposable)

{

MessageBuffer requstBuffer = request.CreateBufferedCopy(int.MaxValue);

Message response = interceptor.Intercept(requstBuffer.CreateMessage());

MessageBuffer responseBuffer = response.CreateBufferedCopy(int.MaxValue);

Console.WriteLine(string.Format("Request:{0}{1}{0}", Environment.NewLine, request));

Console.WriteLine(string.Format("Response:{0}{1}{0}", Environment.NewLine, response));

return responseBuffer.CreateMessage();

}

}

}

}

}

该数据契约有以下两个特点:

  • Intercept的参数和返回值都是Message对象。
  • Operation的Action和ReplyAction为*。

无论参数的个数,类型,次序是怎样的,但WCF的调用最终是基于Message的,也就是参数或返回值最终都会呈现为Message对象。

Operation Selection的匹配规则是:Contract Namespace(default:http://tempuri.org)/Contract Name(default:Interface name)/Action(default:method name)= action in SOAP header。如果将Action设为"*",则意味着该服务的调用,无路SOAP Header中action是什么,都将交付Intercept来处理。

ChannelFactory构造函数的参数,是配置中,Client节点的endpoint的name值。

AddressFilterMode = AddressFilterMode.Any:在上面我们提到过,ChannelDispatcher在选择EndpointDispacher的时候是基于两个Message Filter:Address Filter和Contract Filter。也就是说,ChannelDispatcher通过这两个Filter选择合适Endpoint。在默认的情况下,Address Filter是根据SOAP的To Message Header的URI来进行栓选的,所以需要Endpoint的Address和To Header中的Addres完全匹配。但是在我们CalculateService的例子中,由于Client最终是访问的时CalculateService,所以生成的SOAP的To Headler的地址是CalculateService的地址:http://127.0.0.1:9999/calculateservice,而我们需要是用InterceptService 来处理该请求,Address Filtering肯定是不能通过的。好在我们可以在ServiceBehavior设置AddressFilterMode 来改变Address Filtering的方式。AddressFilterMode = AddressFilterMode.Any意味着,Address Filtering会被忽略。

CreateBufferedCopy:可能有人会奇怪,为什么不对request message和response message进行直接操作(将他们显示在TextBox上)?这是应为Message在WCF有一个特殊的处理机制:只有Message的State为Created的时候,才能获取MessageBody的内容,否则会抛出异常。而我们在对Message进行相应操作的时候,会改变Message 的State(Read,Written,Copied,Closed)。所以对response message来讲,对message的显示实际上将Sate改为Read,如何将response message直接返回到client,对该message的读取操作将是不允许的,所以先调用CreateBufferedCopy创建该message的一个memory buffer,最有返回的时通过该buffer重新创建的Message。

2新建Windows服务,作为上面WCF服务的宿主程序。

代码如下:

namespace MiddleTierWcfWindowsService

{

public partial class Service : ServiceBase

{

ServiceHost host;

public Service()

{

InitializeComponent();

}

protected override void OnStart(string[] args)

{

host = new ServiceHost(typeof(MessageInterceptor.InterceptService));

host.Open();

}

protected override void OnStop()

{

host.Close();

}

}

}

3为Windows服务添加应用程序配置App.config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<system.serviceModel>

<bindings>

<netTcpBinding>

<binding name="aaaaaaaaa" />

</netTcpBinding>

</bindings>

<client>

<endpoint address="net.tcp://bbbbbbbbb"

binding="netTcpBinding" bindingConfiguration="aaaaaaaaa"

contract="eeeeeeeee" name="ccccccccc">

</endpoint>

</client>

<services>

<service name="HHHHHHHHH">

<endpoint binding="netTcpBinding" bindingConfiguration="aaaaaaaaa"

contract="eeeeeeeee"

address="net.tcp://ddddddddd"/>

</service>

</services>

</system.serviceModel>

</configuration>

AAAAAAAAA:这里我使用了NetTcpBinding,作为客户端-》WCF中间层(可信中介)-》AIF服务端的终结点的binding,你也可以选择适合自己的。

BBBBBBBBB:这里是AIF中,服务的URI。

CCCCCCCCC:这里是上面WCF中间层类库接口的实现中,ChannelFactory构造函数的参数,本例中是calculateService。

DDDDDDDDD:这里是WCF中间层的终结点地址。

EEEEEEEEE:是client和service的contract契约,都使用的是WCF中间层类库中的接口的"命名空间+接口名"。本例子中是MessageInterceptor.IIntercept。

HHHHHHHHH:是接口的实现。本例中是MessageInterceptor.InterceptService 。

4设置Windows服务的Service设计视图的ServiceName,用于在日志中显示。

5在Windows服务的Service设计视图上点右键,添加安装程序。

6在新添加的安装程序中,将serviceProcessInstaller1的Account设为LocalService。即,启动时,以本地服务方式登录。

7将serviceInstaller1的Description,DisplayName,ServiceName,都设置下,用于在系统服务中显示。

8安装生成的服务。

9在系统服务中,找到该服务,右键,属性,登录,登录为AX中的系统服务账户,如BC账户,密码为BC账户的密码。

10客户端的配置文件里,新增一个终结点行为。

<system.serviceModel>

<behaviors>

<endpointBehaviors>

<behavior name="FFFFFFFFF">

<clientVia viaUri="net.tcp://DDDDDDDDD" />

</behavior>

</endpointBehaviors>

</behaviors>

<bindings>

<netTcpBinding>

<binding name="AAAAAAAAA" />

</netTcpBinding>

</bindings>

<client>

<endpoint address="net.tcp://BBBBBBBBB"

behaviorConfiguration="FFFFFFFFF"

binding="netTcpBinding" bindingConfiguration="AAAAAAAAA"

contract="GGGGGGGGG" name="CCCCCCCCC">

</endpoint>

</client>

</system.serviceModel>

A、B、C、D、如上面所述。

FFFFFFFFF:终结点行为的名称。

GGGGGGGGG:AIF服务中,"命名空间+数据契约"的名字。本例为,MessageInterceptor.ICalculate

11结束

至此,WCF中间层的转发,已经设置好了。

在客户端,可以以context.LogonAsUser=aaa@bbb.com;的方法,用AX中的账户进行操作,系统会检查该账户的数据权限。在表中,记录的createdBy等系统字段,会显示为该AD用户的别名。

如果使用客户端的人员为一线工人,可能没有AX账户,所以此处建议不设置。表中的createdBy等系统字段,记录是BC账户的别名,使用的是BC的数据权限。

Dynamics AX 2012 R2 Service Middle Tier WCF WCF转发的更多相关文章

  1. Dynamics AX 2012 R2 电子邮件广播错误 0x80040213

    Dynamics AX 2012 R2 电子邮件广播错误 0x80040213 今天Reinhard在新环境做邮件广播测试时,发现无法发送邮件,并报以下错误: 类"CDO.Message&q ...

  2. Dynamics AX 2012 R2 安装Reporting Services 扩展

    今天Reinhard在VS中部署SSRS报表时,接到以下错误: 部署因错误而被取消.在报表服务器上,验证:-SQL Server Reporting Services 服务是否正在运行. 接着,Rei ...

  3. Dynamics AX 2012 R2 如何处理运行时间较长的报表

    当处理的数据量较多,逻辑比较复杂时,报表可能会超时.为了解决这个问题,Reinhard一直使用SrsReportDataProviderPreProcess来做预处理报表.它会在调用SSRS前,在AX ...

  4. Dynamics AX 2012 R2 安装额外的AOS

    众所周知,AX系统分为三层:Client,Application Server,Database Server. 我们添加额外的Application Server主要是出于以下两个原因: 使用多台服 ...

  5. Dynamics AX 2012 R2 业务系列-销售业务流程

    在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 1.销售的主要职责 其实这里说的职责主要是针对销售文员,并非整天外面满世界跑业 ...

  6. Dynamics AX 2012 R2 业务系列-采购业务流程

    在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 国际惯例,从采购开始. 1.采购的主要职责 简单点说,采购的主要职责,是从供应 ...

  7. Dynamics AX 2012 R2 安装 AIF IIS上的Web服务

    1.为什么使用IIS上的WEB服务 组件? 如果你要在Dynamics AX Service中使用HTTP Adapter,那么你就要安装IIS上的WEB服务 组件.HTTP Adapter会在IIS ...

  8. Dynamics AX 2012 R2 业务系列

    在之前的一系列博文里,Reinhard介绍了Dynamics AX Demo的安装与配置.相信同学们看完后,都已经成功拥有了一个测试环境. 众所周知的是,ERP作为一个特殊的软件系统,他有着背后的业务 ...

  9. [译]Dynamics AX 2012 R2 BI系列-规划分析的注意事项

    https://msdn.microsoft.com/en-us/library/gg731898.aspx       在开始实施AX的分析特性前,有很多事情要考虑.本文描述了你必须考虑的事情,和在 ...

随机推荐

  1. 30天,O2O速成攻略【7.25北京站】

    活动概况 时间:2015年7月25日13:30-16:30 地点:车库咖啡(北京市海淀西大街48号鑫鼎宾馆二层) 主办:APICloud.领通科技.快易行 网址:www.apicloud.com 费用 ...

  2. RouteOS软路由HotSpot热点认证网关

    实现要求: 实现局域网有线无线需在网页输入用户名和密码登录,不同用户登录有不同的访问内外网权限. 环境要求: 一台PC机安装三张网卡,第一张网卡连接外网,第二张网卡配置局域网,第三张网卡做配置连接使用 ...

  3. [SharpDevelop]菜单状态更新

    方式一 在Idle方法中更新 void OnApplicationIdle(object sender, EventArgs e) { // Use the Idle event to update ...

  4. @propetry参数

    // //  Person.h //  01-手动内存管理基本概念 // //  Created by apple on 14-3-17. // // #import <Foundation/F ...

  5. 动画的button(按下时缩小,松开时恢复)

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

  6. C# 字典 Dictionary<Tkey,Tvalue>

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来.我们都知道计算机技术发展日新月异,速度惊人的快,你我稍不留神,就会被慢慢淘汰!因此:每日不间断的学习是避免被 ...

  7. docker operation method note

    docker stop script #!/bin/bash CID_LIST=$(docker ps -q | xargs)if [ "$CID_LIST" = "&q ...

  8. sql语句感想

    select出来内容可以当成表拿来用,,比如取别名什么的. union是纵向的,追加记录(行) join on是横向的,追加列

  9. JQuery实现页面企业广告图片切换和新闻列表滚动效果

    最近用到一个页面上图片左右切换和新闻列表滚动呈现的效果,整理如下: 前段代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...

  10. [原创]Scala学习:数组的基本操作,数组进阶操作,多维数组

    1.Scala中提供了一种数据结构-数组,其中存储相同类型的元素的固定大小的连续集合.数组用于存储数据的集合,但它往往是更加有用认为数组作为相同类型的变量的集合 2 声明数组变量: 要使用的程序的数组 ...