我正在构建一些具有公共标头的服务。该头部在请求中具有某种布局,并且在响应中具有不同的布局(即,存在两个类别)。
但是,当我添加引用或使用svcutil时,会在请求和响应类型中生成具有相同标头的代理。
例如:
[MessageContract]
class Contract<THeader, TBody>
{
[MessageHeader] public THeader Header { get; set; }
[MessageBodyMember] public TBody Body { get; set; }
}
class MyRequestHeader
{
public string RequestorId { get; set; }
}
class MyResponseHeader
{
public string ErrorMessage { get; set; }
}
OperationContract类似于:
[OperationContract]
public Contract<MyResponseHeader, ResponseBody> Process(Contract<MyRequestHeader, RequestBody> data);
代理变成类似:
var client = new ...;
var header = new MyRequestHeader();
var body = new RequestBody();
**ResponseBody**
response = client.Process(ref header, body);
如您所见,标题(Request)作为ref传递;这可能意味着WCF在请求和响应中具有相同的标头。并且MyResponseHeader消失了。
任何人都可以对这个问题有所了解吗?
答案 0 :(得分:6)
这里有一些奇怪的事情。
我尝试重现您的问题,并得到以下结果(我必须标记某些类型public
,并将[DataContract]
添加到您的标题类中。
以下是WSDL的视图:
生成的代码(svcutil 4.0.30319.18046)也在响应消息中使用MyRequestHeader
:
这是由以下XSD引起的:
正如您所看到的,只有一个实例为&#34; Header&#34;类。
我尝试为泛型类创建类型,如下所示:
[MessageContract]
public abstract class Contract<THeader, TBody>
{
[MessageHeader]
public THeader Header { get; set; }
[MessageBodyMember]
public TBody Body { get; set; }
}
[DataContract(Name="RequestHeader")]
public class MyRequestHeader
{
public string RequestorId { get; set; }
}
[DataContract(Name = "ResponseHeader")]
public class MyResponseHeader
{
public string ErrorMessage { get; set; }
}
[MessageContract]
public class RequestContract : Contract<MyRequestHeader, string>
{ }
[MessageContract]
public class ResponseContract : Contract<MyResponseHeader, string>
{ }
[ServiceContract]
public interface IService1
{
[OperationContract]
ResponseContract Process(RequestContract data);
}
但是这并没有解决问题,生成的客户端ResponseContract仍然是使用RequestHeader类型的Header生成的。
甚至更改服务代码以使用两种不同的消息合同:
[DataContract(Name="RequestHeader")]
public class MyRequestHeader
{
public string RequestorId { get; set; }
}
[DataContract(Name = "ResponseHeader")]
public class MyResponseHeader
{
public string ErrorMessage { get; set; }
}
[MessageContract]
public class RequestContract<TBody>
{
[MessageHeader]
public MyRequestHeader Header { get; set; }
[MessageBodyMember]
public TBody Body { get; set; }
}
[MessageContract]
public class ResponseContract<TBody>
{
[MessageHeader]
public MyResponseHeader Header { get; set; }
[MessageBodyMember]
public TBody Body { get; set; }
}
[ServiceContract]
public interface IService1
{
[OperationContract]
ResponseContract<string> Process(RequestContract<string> data);
}
无法解决问题:
甚至删除所有共享继承和泛型,如下所示:
[DataContract(Name="RequestHeader")]
public class MyRequestHeader
{
public string RequestorId { get; set; }
}
[DataContract(Name = "ResponseHeader")]
public class MyResponseHeader
{
public string ErrorMessage { get; set; }
}
[MessageContract(WrapperName="RequestMessage")]
public class RequestContract
{
[MessageHeader]
public MyRequestHeader Header { get; set; }
[MessageBodyMember]
public string Body { get; set; }
}
[MessageContract(WrapperName = "ResponseMessage")]
public class ResponseContract
{
[MessageHeader]
public MyResponseHeader Header { get; set; }
[MessageBodyMember]
public string Body { get; set; }
}
[ServiceContract]
public interface IService1
{
[OperationContract]
ResponseContract Process(RequestContract data);
}
仍会导致在ResponseMessage中使用RequestHeader。
我认为答案在于this documentation:
WSDL注意事项
生成Web服务描述时 来自使用消息契约的服务的语言(WSDL)契约, 重要的是要记住并非所有的邮件合同功能都是 反映在生成的WSDL中 [原文如此]。请考虑以下几点:WSDL 无法表达标题数组的概念。创建时 带有一个标题数组的消息使用 MessageHeaderArrayAttribute,生成的WSDL只反映一个 标题而不是数组。
生成的WSDL文档可能无法反映某些保护级别 信息。
WSDL中生成的消息类型与类具有相同的名称 消息合同类型的名称。
在多个操作中使用相同的消息合同时,多个 消息类型在WSDL文档中生成。这些名字都是 通过添加数字&#34; 2&#34;,&#34; 3&#34;等来进行后续使用。 导回WSDL时,有多种消息协定类型 创建并且除了名字之外完全相同。