如何:截获数据服务消息(WCF 数据服务)
使用 WCF 数据服务 可以截获请求消息,以便可以向操作添加自定义逻辑。 若要截获消息,请使用数据服务中的专门特性化的方法。 有关更多信息,请参见侦听器(WCF 数据服务)。
本主题中的示例使用 Northwind 示例数据服务。 此服务是在完成 WCF 数据服务快速入门时创建的。
为 Orders 实体集定义查询侦听器
在 Northwind 数据服务项目中,打开 Northwind.svc 文件。
在 Northwind 类的代码页中,添加以下 using 语句(在 Visual Basic 中为 Imports)。
Imports System.Linq.Expressions
using System.Linq.Expressions;
在 Northwind 类中,定义一个名为 OnQueryOrders 的服务操作方法,如下所示:
' Define a query interceptor for the Orders entity set. <QueryInterceptor("Orders")> _ Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))
// Define a query interceptor for the Orders entity set. [QueryInterceptor("Orders")] public Expression<Func<Order, bool>> OnQueryOrders()
为 Products 实体集定义变更侦听器
在 Northwind 数据服务项目中,打开 Northwind.svc 文件。
在 Northwind 类中,定义一个名为 OnChangeProducts 的服务操作方法,如下所示:
' Define a change interceptor for the Products entity set. <ChangeInterceptor("Products")> _ Public Sub OnChangeProducts(ByVal product As Product, _ ByVal operations As UpdateOperations)
// Define a change interceptor for the Products entity set. [ChangeInterceptor("Products")] public void OnChangeProducts(Product product, UpdateOperations operations)
示例
下面的示例为 Orders 实体集定义一个返回 lambda 表达式的查询侦听器方法。 此表达式包含一个委托,该委托基于具有特定联系人姓名的相关 Customers 筛选所请求的 Orders。 该姓名反过来又由请求的用户确定。 此示例假定数据服务承载在使用 WCF 的 ASP.NET Web 应用程序中,并且已启用身份验证。 HttpContext 类用于检索当前请求的原则。
' Define a query interceptor for the Orders entity set.
<QueryInterceptor("Orders")> _
Public Function OnQueryOrders() As Expression(Of Func(Of Order, Boolean))
' Filter the returned orders to only orders
' that belong to a customer that is the current user.
Return Function(o) o.Customer.ContactName = _
HttpContext.Current.User.Identity.Name
End Function
// Define a query interceptor for the Orders entity set.
[QueryInterceptor("Orders")]
public Expression<Func<Order, bool>> OnQueryOrders()
{
// Filter the returned orders to only orders
// that belong to a customer that is the current user.
return o => o.Customer.ContactName ==
HttpContext.Current.User.Identity.Name;
}
下面的示例为 Products 实体集定义变更侦听器方法。 此方法验证对该服务的 Add 或 Change 操作的输入,如果对断货的产品进行更改,则会引发异常。 此方法还将删除产品操作视为不支持的操作,从而阻止这一操作。
' Define a change interceptor for the Products entity set.
<ChangeInterceptor("Products")> _
Public Sub OnChangeProducts(ByVal product As Product, _
ByVal operations As UpdateOperations)
If operations = UpdateOperations.Change Then
Dim entry As System.Data.Objects.ObjectStateEntry
If Me.CurrentDataSource.ObjectStateManager _
.TryGetObjectStateEntry(product, entry) Then
' Reject changes to a discontinued Product.
' Because the update is already made to the entity by the time the
' change interceptor in invoked, check the original value of the Discontinued
' property in the state entry and reject the change if 'true'.
If CType(entry.OriginalValues("Discontinued"), Boolean) Then
Throw New DataServiceException(400, String.Format(
"A discontinued {0} cannot be modified.", product.ToString()))
Else
Throw New DataServiceException(String.Format( _
"The requested {0} could not be found in the data source.", product.ToString()))
End If
ElseIf (operations = UpdateOperations.Delete) Then
' Block the delete and instead set the Discontinued flag.
Throw New DataServiceException(400, _
"Products cannot be deleted; instead set the Discontinued flag to 'true'")
End If
End If
End Sub
// Define a change interceptor for the Products entity set.
[ChangeInterceptor("Products")]
public void OnChangeProducts(Product product, UpdateOperations operations)
{
if (operations == UpdateOperations.Change)
{
System.Data.Objects.ObjectStateEntry entry;
if (this.CurrentDataSource.ObjectStateManager
.TryGetObjectStateEntry(product, out entry))
{
// Reject changes to a discontinued Product.
// Because the update is already made to the entity by the time the
// change interceptor in invoked, check the original value of the Discontinued
// property in the state entry and reject the change if 'true'.
if ((bool)entry.OriginalValues["Discontinued"])
{
throw new DataServiceException(400, string.Format(
"A discontinued {0} cannot be modified.", product.ToString()));
}
}
else
{
throw new DataServiceException(string.Format(
"The requested {0} could not be found in the data source.", product.ToString()));
}
}
else if (operations == UpdateOperations.Delete)
{
// Block the delete and instead set the Discontinued flag.
throw new DataServiceException(400,
"Products cannot be deleted; instead set the Discontinued flag to 'true'");
}
}