zoukankan      html  css  js  c++  java
  • D365 FO第三方集成(三)---服务实现

    D365 FO的Custom Service的实现比AX2012简单了很多。
    AX2012服务方法要用属性SysEntryPointAttribute标记,添加到Services以后,还要发布服务并在系统管理入站端口添加操作,服务运行在CIL下,所以每次改动服务方法的代码都要增量生成CIL。
    AX2012只支持SOAP,不支持Restful,个人偏爱Restful,主要是SOAP的代理类在不同的平台有说不清道不明的问题,在AX2012的时候,我是通过.NET WCF封装了一下,把SOAP封装成了Restful的服务。
    在D365 FO这些问题都不是问题了,任何类都可以直接添加到Services节点,服务方法不需要再用SysEntryPointAttribute标记。只要把Services节点添加到Service Groups,D365 FO就直接把类里的方法
    暴露成SOAP和Json-Based服务。
    D365 FO没有称呼Restful服务而是称为json-based服务。
    Restful和json-based这两个东西不是一个层面的东西,Restful是一种网络应用程序的设计风格和开发方式,Restful的数据传输既可以用json也可以用xml,也可以用其他格式。
    在.NET WCF Restful实现里是通过Content-Type来识别的。根据Content-Type来决定调用方传过来的数据是什么格式的,可以是xml,json,也可以是text/plain。
    D365 FO里的服务称为Json-base服务,顾名思义调用服务方法的时候入参和返回值都必须是合法的json格式。
    这个跟WCF Restful的RequestFormat和ResponseFormat格式指定Json,http request的ContentType指定为json是一样的。
    框架负责反序列化和序列化,个人不是很喜欢这种方式,异常不是很容易捕获,如果第三方传入的数据有问题,序列化失败会内部错误500,不好排错。
    另外第三方提供的入参也不一定就是合法的json格式,可能就是一堆没有规律的字符串,传入以后再作分析可能更方便。
    WCF Restful可以直接接收text/plain,方法入参用System.IO.Stream,接收以后再做分析。
    既然D365 FO只支持Json格式,我觉得把第三方提供的数据都作为一个字符串,封装到json里,作为一个入参传入,方法接收以后再根据数据情况分析可能更灵活。
    当然这个每个人都有自己的偏好,怎么实现都可以。
    以D365提供的示例代码为例说明步骤:
    1.创建类Class1,添加方法

     1 class Class1
     2 {
     3     public str EchoString(str input)
     4     {
     5         return input;
     6     }
     7 
     8     public ComplexContract1 GetComplexContract()
     9     {
    10         ComplexContract1 complexContract = new ComplexContract1();
    11         List contractList = new List(Types::Class);
    12         Contract1 contract = new Contract1();
    13         contract.parmStringMember("SomeString");
    14         contractList.addEnd(contract);
    15         contract = new Contract1();
    16         contract.parmStringMember("SomeString2");
    17         contractList.addEnd(contract);
    18         complexContract.parmContractList(contractList);
    19         return complexContract;
    20     }
    21 
    22     public ComplexContract1 EchoComplexContract(ComplexContract1 input)
    23     {
    24         return input;
    25     }
    26 
    27     [AifCollectionTypeAttribute('return', Types::Class, classStr(Contract1))]
    28     public List GetContractList()
    29     {
    30         List contractList = new List(Types::Class);
    31         Contract1 contract = new Contract1();
    32         contract.parmStringMember("SomeString");
    33         contractList.addEnd(contract);
    34         contract = new Contract1();
    35         contract.parmStringMember("SomeString2");
    36         contractList.addEnd(contract);
    37         return contractList;
    38     }
    39 
    40     [AifCollectionTypeAttribute('return', Types::Class, classStr(Contract1)),
    41         AifCollectionTypeAttribute('input', Types::Class, classStr(Contract1))]
    42     public List EchoContractList(List input)
    43     {
    44         return input;
    45     }
    46 
    47 }

    因为D365 FO目前(10.0.0.10)还不支持泛型,所以List作为入参和返回值的时候,需要用属性指定List里class的类型,这样通知序列化框架应该用哪个类进行序列化和反序列化。
    试了一下,D365 FO(10.0.0.10)的服务方法已经支持返回.NET的类型了,所以在C#里定义一个继承泛型List的类,用来做入参和返回值,这样也就不用List了。
    不过正如前文说的,个人不是很喜欢直接返回实体,入参和返回值直接用字符串更直接。
    所以我自己封装的话,都会是这样的方法

    public str EchoString(str input)
        {
            return input;
        }

    至于序列化和反序化还是在方法体内进行吧。
    2.定义Service
    在Project里新增Service,然后关联Class1

     3.新增Service Group,把Service1添加到Service Group

    编译程序,服务器端的代码就这么简单。
    下一篇blog介绍一下客户端如何调用服务器端方法。

  • 相关阅读:
    关于JSONP
    使用stylelint对CSS/Sass做代码审查
    关于input的file框onchange事件触发一次失效的新的解决方法
    HTML5 之 FileReader(图片上传)
    document.domain
    window.hostory(浏览器的历史记录)
    事件DOMContentLoaded和load的区别
    JavaScript中---作用域
    关于repaint(重绘)和reflow( 回流)
    bootstrap兼容性问题
  • 原文地址:https://www.cnblogs.com/Farseer1215/p/13121757.html
Copyright © 2011-2022 走看看