设计SOA WCF Web服务时的最佳实践是什么?

11

假设有一个操作合同,例如:

[OperationContract]
void Operation(string param1, string param2, int param3);

这个可以重新设计为:

[MessageContract]
public class OperationRequest
{
    [MessageBodyMember]
    public string Param1 { get; set; }

    [MessageBodyMember]
    public string Param2 { get; set; }

    [MessageBodyMember]
    public int Param3 { get; set; }
}

[MessageContract]
public class OperationResponse
{
}

[OperationContract]
OperationResponse Operation(OperationRequest request);

我喜欢MessageContract的一点是我可以更加明确地控制SOAP消息的格式。

同样,我可以编写几乎相同的代码,但使用DataContract:

[DataContract]
public class OperationRequest
{
    [DataMember]
    public string Param1 { get; set; }

    [DataMember]
    public string Param2 { get; set; }

    [DataMember]
    public int Param3 { get; set; }
}

[DataContract]
public class OperationResponse
{
}

[OperationContract]
OperationResponse Operation(OperationRequest request);
我喜欢DataContract的一个特点是我可以定义IsRequired、Order和Name。
今天,我预计唯一的使用者将是WCF客户端。然而,我想要先设计合同并尽可能地遵循SOA实践。不想让WCF指定我的SOAP、WSDL和XSD,我想让XML定义WCF层,但使用WCF生成它,以免向WCF添加任何自定义消息处理。我想遵循最常见的SOA XML约定,也就是所有标签都以小写字母开头 - 我是对的吗?同时,我想尽可能具有版本容忍性。
是否明智总是像这样创建请求和响应消息?这三种格式中哪种促进了最佳的SOA实践?我是否应该再进一步定义DataContract和MessageContract,其中MessageContract仅包含DataContract?或者,如果我真正暴露了新类型(即不要创建消息类型作为容器),我应该只使用DataContract?
这是一组复杂的问题,但我正在努力找到答案,我不确定将问题分开是否提供了足够的上下文来获得我要寻找的答案。
4个回答

15

最好的实践是不要在操作契约中使用多个参数,而应该使用一个类型来包装所有需要的参数,这样有助于长期维护。当您添加一个新的可选参数时,现有的客户端不会出错。

我在一个商业集成团队工作,我们经常与其他公司进行集成(AT&T、Cox、Exxon...),但从未见过需要多个参数的 Web 服务调用。


我们也有同样的做法。我们将所有内容都封装到单个请求和响应对象中。 - Rebecca

6

XML通常使用驼峰命名法。 WSDLXML Schema对元素和属性都使用驼峰命名法,例如查看syntaxschema

为什么SOAP被定义为不同的方式,我不知道,但它使用帕斯卡命名法用于元素和属性,查看here

类似地,大多数WS*规范(也许全部)使用帕斯卡命名法用于元素和属性,参见here。 XML Schema不关心其所定义的XML类型的约定。

Thomas Erl写了许多与SOA相关的重要书籍,包括“面向服务的架构”。在第13章和第15章中,他提供了许多关于典型事务各个部分的XML示例。它使用PascalCasing在XML Schema中定义类型和对象成员,这与C#类和属性命名的常规模式非常匹配。因此,默认情况下WCF已经非常符合标准。
关于实际消息命名,一些约定使用camelCasing,而另一些则使用PascalCasing,因此我的首选是匹配主要语言需求,在WCF的情况下是PascalCasing。并且WCF默认值与如何编写请求和响应消息的某些示例非常匹配,这里有一些示例
因此,现在唯一未解决的问题就是如何在使用OperationContractDataContract和/或MessageContract方面进行标准化的基本问题。

只有在您拥有复杂类型(在 XSD 术语中)时,才有意义定义 DataContract。我倾向于认为像 Terry 指出的 YAGNI(You Ain't Gonna Need It)是正确的选择,但 Erl 似乎建议一个更加过程密集型的版本,因此我仍然不确定最好的方法是使用作为我的默认选择(问题的主要部分)。


3
为什么这个答案是社区维基?这是一个很好的答案,vjrobinson应该因此获得他/她应得的声誉。 - Damian Powell

0

我认为这取决于具体情况。如果你只是交换简单类型(例如字符串),那么使用OperationContract是可以接受的。

当你想要修改消息格式时,应该使用MessageContract;当你想要表示复杂类型(例如地址)时,应该使用DataContract。


0

这里想到了YAGNI

我认为不要过度追求未来的花哨外观。WCF已经很好地支持面向服务的架构。总的来说,我建议遵循默认设置,并在确有需要进行复杂操作时小心耦合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接