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的分析特性前,有很多事情要考虑.本文描述了你必须考虑的事情,和在 ...
随机推荐
- Spring中的工厂模式和单例模式
Spring预备知识(适合中小型项目) 作用:集成和管理其他框架 工厂模式: A a = new A( ); 将类所要创建的对象写入工厂,统一进行管理 package com.spring; pu ...
- mongoose的promise(转发)
Switching out callbacks with promises in Mongoose Published on July 28, 2015 mongo node mongoose pro ...
- Android --MainActivity模板
系统自带的NavigationDrawerFragment 1.自动生成NavigationDrawerFragment,onCreatView代码如下 @Override public View o ...
- 请求转发(Forward)和重定向(Redirect)的区别
forward(转发): 是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在 ...
- Java8 新特性default
在JDK1.8的Iterator接口中 package java.util; import java.util.function.Consumer; public interface Iterator ...
- 第八篇 Replication:合并复制-How it works
本篇文章是SQL Server Replication系列的第八篇,详细内容请参考原文. 在这一系列的前几篇你已经学习了如何在多服务器环境中配置合并复制.这一篇将介绍合并代理并解释它在复制过程中扮演的 ...
- javascript实例学习之二——类新浪微博的输入框
该案例实现如下效果,具体可见新浪微博网站的微博发布框 实现 以下效果效果1:当光标移入文本框时,文本框上方的文字发生变化,显示剩余可以输入的字数,当光标移出文本框,并且文本框中没有任何输入时,恢复最初 ...
- Java基础之写文件——创建通道并且写文件(TryChannel)
控制台程序,创建一个文件并且使用通道将一些文本写入到这个文件中. import static java.nio.file.StandardOpenOption.*; import java.nio.c ...
- keil 编译的一些错误
以前使用的是MDK4.5 但是没有stm32F3的元器件,果断的使用了4.6版本了.但是编译之后出现这样错误:linking....\Obj\prj.axf: Warning: L6373W: lib ...
- XML工程配置文件的读写
TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Windows或Linux中编译,使用TinyXML进行C++ XML解析,使用简单,容易上手.这个解析库的模型通过解析XML文件, ...