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的分析特性前,有很多事情要考虑.本文描述了你必须考虑的事情,和在 ...
随机推荐
- struts标签小记
1.<s:iterator>标签的 奇偶数行使用不同样式 <s:iterator id="list" value="#request.listq&qu ...
- 【转】Tomcat组件生命周期管理
Tomcat组件生命周期管理 Tomcat中Server,Service,Connector,Engine,Host,Context,它们都实现了org.apache.catalina.Lifecyc ...
- 示sudo: cd: command not found
执行sudo cd 时出现 sudo: cd: command not found 原因shell shell是一个命令解析器 所谓shell是一个交互式的应用程序. shell执行外部命令的 时候, ...
- PostgreSQL Insight Monitor pgstat
PostgreSQL Insight Monitor pgstat pgstat 是一个连接到数据库并获取数据库的活动状态的命令行工具. PostgreSQL有许多状态: archiver for ...
- PostgreSQL Partitions
why we need partitions The first and most demanding reason to use partitions in a database is to inc ...
- Leetcode: Frog Jump
A frog is crossing a river. The river is divided into x units and at each unit there may or may not ...
- G面经prepare: Friends Recommendation
想想如果你用linkedin或者facebook, 给你一个人和他的朋友关系网,你会怎么给一个人推荐朋友 一个例子就是A-B, A-C, B - D, B - E, C - D,这个时候问我应该推荐谁 ...
- spring 官方下载地址
SPRING官方网站改版后,建议都是通过Maven和Gradle下载,对不使用Maven和Gradle开发项目的,下载就非常麻烦. 下给出Spring Framework jar官方直接下载路径: h ...
- struts2 标签为简单标签
<s:form method="post" action="" theme="simple"> <s:textfield ...
- hduoj 4706 Children's Day 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4706 Children's Day Time Limit: 2000/1000 MS (Java/Others) ...