Dynamics AX 2012 R2 Service Middle Tier WCF WCF转发
参考了蒋金楠老师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) {
{ 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转发的更多相关文章
- Dynamics AX 2012 R2 电子邮件广播错误 0x80040213
Dynamics AX 2012 R2 电子邮件广播错误 0x80040213 今天Reinhard在新环境做邮件广播测试时,发现无法发送邮件,并报以下错误: 类"CDO.Message&q ...
- Dynamics AX 2012 R2 安装Reporting Services 扩展
今天Reinhard在VS中部署SSRS报表时,接到以下错误: 部署因错误而被取消.在报表服务器上,验证:-SQL Server Reporting Services 服务是否正在运行. 接着,Rei ...
- Dynamics AX 2012 R2 如何处理运行时间较长的报表
当处理的数据量较多,逻辑比较复杂时,报表可能会超时.为了解决这个问题,Reinhard一直使用SrsReportDataProviderPreProcess来做预处理报表.它会在调用SSRS前,在AX ...
- Dynamics AX 2012 R2 安装额外的AOS
众所周知,AX系统分为三层:Client,Application Server,Database Server. 我们添加额外的Application Server主要是出于以下两个原因: 使用多台服 ...
- Dynamics AX 2012 R2 业务系列-销售业务流程
在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 1.销售的主要职责 其实这里说的职责主要是针对销售文员,并非整天外面满世界跑业 ...
- Dynamics AX 2012 R2 业务系列-采购业务流程
在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 国际惯例,从采购开始. 1.采购的主要职责 简单点说,采购的主要职责,是从供应 ...
- Dynamics AX 2012 R2 安装 AIF IIS上的Web服务
1.为什么使用IIS上的WEB服务 组件? 如果你要在Dynamics AX Service中使用HTTP Adapter,那么你就要安装IIS上的WEB服务 组件.HTTP Adapter会在IIS ...
- Dynamics AX 2012 R2 业务系列
在之前的一系列博文里,Reinhard介绍了Dynamics AX Demo的安装与配置.相信同学们看完后,都已经成功拥有了一个测试环境. 众所周知的是,ERP作为一个特殊的软件系统,他有着背后的业务 ...
- [译]Dynamics AX 2012 R2 BI系列-规划分析的注意事项
https://msdn.microsoft.com/en-us/library/gg731898.aspx 在开始实施AX的分析特性前,有很多事情要考虑.本文描述了你必须考虑的事情,和在 ...
随机推荐
- 清除Outlook 2013中缓存的邮件地址
1.删除相关文件(可能会没有访问权限): 路径:C:\Documents and Settings\user\用户名\Application Data\Microsoft\Outlook 文件名:ou ...
- OC 对象和匿名对象
OC 对象和匿名对象 对象和匿名对象的定义: 当new出一个对象时,如果用一个指针接收这个对象,那么这个指针通常被称为对象. 如果new出的对象,不用指针接收,那么这个对象就称为匿名对象. #impo ...
- IIS 相关
Restart IIS: run "iisreset" command check port usage: netstat -ano How to set up SSL in II ...
- ajax异步提交文件
首先 下载jquery和jquery.form.js http://malsup.com/jquery/form/ <script type="text/javascript&qu ...
- oracle组建:ODAC112021Xcopy_x64,在开发机上,不用安装oracle的客户端等开发
以下解决方案是为了连接远程服务器上的oracle 11g 的解决方案. 下载地址:http://www.oracle.com/technetwork/database/windows/download ...
- 如何用Java解析CSV文件
首先看一下csv文件的规则: csv(Comma Separate Values)文件即逗号分隔符文件,它是一种文本文件,可以直接以文本打开,以逗号分隔.windows默认用excel打开.它的格式包 ...
- 为什么要在block用weak self
block会给内部所有的对象引用计数加一,这一方面会带来潜在的retain cycle,不过我们可以通过Weak Self的手段解决.另一方面比较重要就是,它会延长对象的生命周期. 在block前面写 ...
- python自动化运维之路~DAY1
python自动化运维之路~DAY1 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.文件大小单位单位换算 我们一起看一下下面的图: 没错,都是数字,而且这些数字都是二进制的数字 ...
- [原创] 在spring 中使用quarts
1.使用maven加载 quarts 的jar <dependency> <groupId>org.quartz-scheduler</groupId> <a ...
- SparkSQL基础应用(1.3.1)
一.概述 从1.3版本开始Spark SQL不再是测试版本,之前使用的SchemaRDD重命名为DataFrame,统一了Java和ScalaAPI. SparkSQL是Spark框架中处理结构化数据 ...