WCF 约定中的 HTTP 动词
在 .NET Framework 3.5 中使用 WCF 进行 HTTP 编程可以轻而易举地将服务约定中的操作映射到 HTTP 动词。顾名思义,将 WebGetAttribute 应用到某个操作可以使该操作能够通过 HTTP GET 使用。正如您在前面的代码片段中所见,WebGetAttribute 定义了一个名为 UriTemplate 的实例属性。
WebGetAttribute 类型还有一些其他实例属性。最引人注目的是 RequestFormat 和 ResponseFormat。如其名称所指,这些属性的值指明了操作的消息格式。RequestFormat 和 ResponseFormat 属性都属于 WebMessageFormat 类型,即一种具有两个值的枚举类型:Xml 和 Json。WCF 基础结构会使用这些属性的值,借用合适的消息编码器来设置通道堆栈。
WebMessageFormat.Xml 的属性值将产生使用 XML 编码器的通道堆栈。将值设置为 WebMessageFormat.Json 将产生使用 .NET Framework 3.5 中的 JSON 编码器的通道堆栈。由于 HTTP 消息交换的双方都有各自的属性,因此一个应用程序可以实现接收 XML 消息并返回 JSON 消息(反之亦然)。
另一个与 HTTP 动词相关的属性是 WebInvokeAttribute。将此属性应用到操作会使该操作可以被除 HTTP GET 以外的其他任何 HTTP 动词所使用。对象模型中 HTTP GET 和所有其他动词之间的这种区别反映了 HTTP GET 相对于其他 HTTP 动词的使用频率。WebInvokeAttribute 对象模型与 WebGetAttribute 类似,但它包含一个名为 Method 的实例属性。此属性的值可以将某个特殊 HTTP 动词与操作相关联。Method 属性具有 String 类型,因此您可以将值设置为任何标准的 HTTP 动词,甚至是非标准的 HTTP 动词。图 3 阐明了如何在服务约定中使用 WebInvokeAttribute。
Figure 3 Using WebInvokeAttribute
[ServiceContract]
public interface IPictureService
{
[OperationContract]
[WebGet(UriTemplate = "picture/{pictureId}")]
Stream GetPicture(String pictureId);
[OperationContract]
[WebGet(UriTemplate = "picture/t/{pictureId}")]
Stream GetPictureThumbnail(String pictureId);
[OperationContract]
[WebInvoke(UriTemplate="update", Method="POST")]
void UpdatePictureInfo(PictureInfo info);
}
public interface IPictureService
{
[OperationContract]
[WebGet(UriTemplate = "picture/{pictureId}")]
Stream GetPicture(String pictureId);
[OperationContract]
[WebGet(UriTemplate = "picture/t/{pictureId}")]
Stream GetPictureThumbnail(String pictureId);
[OperationContract]
[WebInvoke(UriTemplate="update", Method="POST")]
void UpdatePictureInfo(PictureInfo info);
}
UpdatePictureInfo 方法拥有一个 PictureInfo 类型的参数。在运行时,PictureInfo 对象的序列化版本是 HTTP POST 消息的负载。通过这种方式传递数据,可以让应用程序传输 URI 中无法表达的复杂数据类型。
.NET Framework 3.5 中的 WCF 还可以使与 HTTP 标头交互变得很简便。请求和响应 HTTP 标头是通过 System.ServiceModel.Web.WebOperationContext 类型提供的。WebOperationContext 类型是对 System.ServiceModel.OperationContext 类型(在 .NET Framework 3.0 的 WCF 中引入)的扩展,并且它的使用模式相似。两者都适用于服务对象实现的内部。WebOperationContext 类型提供了一些成员,它们简化了读取或设置 HTTP 标头值,并且简化了检索与访问服务对象所用的 URI 相关的信息。HTTP 标头以集合的形式存储,最常用的标头则作为单独的属性提供。下例表明如何通过为 HTTP 响应设置 Content-Type 标头,使用 WebOperationContext 类型沿用 Web 的数据模型:
public Stream GetPicture(string pictureId)
{
// retrieve the Stream (omitted)
Stream stream;
// set the Content-Type to image/jpeg
WebOperationContext.Current.OutgoingResponse.ContentType =
"image/jpeg";
return stream;
}
{
// retrieve the Stream (omitted)
Stream stream;
// set the Content-Type to image/jpeg
WebOperationContext.Current.OutgoingResponse.ContentType =
"image/jpeg";
return stream;
}