Data Service - 2. 数据服务 (1)
[ 2009-04-23 11:30:44 | 作者: yuhen ]
1. 服务操作
除了公开 "数据" 外,服务通常还包含一些基本的应用逻辑。比如 User Service 通常会包含 Register,毕竟 Password 加密算法不会被其他服务所知晓和引用。
为了便于测试,我们可以用 Fiddler 的 Request Builder 功能来测试 Data Service。
注意选择 Post 方式,而且不能省略单引号。
SetServiceOperationAccessRule 用于设定服务方法的权限,我们可以直接给出具体的方法名或用 "*" 表示全部方法。和 WCF RESTful 相同,WebGet 和 WebInvoke 特性用于设定请求方式。
Data Service 对服务操作有一些具体的限制。
Data Service 通过判断 Request Accept 来决定返回格式。我们返回 JSON 结果。
我们还可以添加查询选项,比如排序。
http://localhost:2394/Test.svc/Users2?minAge=14&$orderby=Age%20desc
注意:Data Service 对 URI 中的参数和属性名称区分大小写。
2. 侦听器
所谓侦听器就是 Data Service 允许我们截获请求,并添加自定义逻辑的一种手段。通常用于添加一些附加规则或者进行访问身份验证。
当请求 http://localhost:2394/Test.svc/Users 时,我们会发现 user1 被过滤掉。这种方式很有用,比如过滤掉管理员信息。
我们可以用类似下面这样的方式来验证访问者信息,以便决定返回策略。
当然,实际的验证策略可能是用户身份信息。 还有就是查询侦听器不能包含参数。
另外一种侦听器是针对修改行为的。
当客户端增加一个包含 "admin" 字符串的用户时,将触发异常。
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=807
除了公开 "数据" 外,服务通常还包含一些基本的应用逻辑。比如 User Service 通常会包含 Register,毕竟 Password 加密算法不会被其他服务所知晓和引用。
public class Test : DataService<TestEntities>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
[WebInvoke(Method="Post")]
public void Register(string username, int age)
{
this.CurrentDataSource.AddToUsers(new User { Name = username, Age = age });
this.CurrentDataSource.SaveChanges();
}
}为了便于测试,我们可以用 Fiddler 的 Request Builder 功能来测试 Data Service。
注意选择 Post 方式,而且不能省略单引号。
SetServiceOperationAccessRule 用于设定服务方法的权限,我们可以直接给出具体的方法名或用 "*" 表示全部方法。和 WCF RESTful 相同,WebGet 和 WebInvoke 特性用于设定请求方式。
Data Service 对服务操作有一些具体的限制。
- 此方法只能接受 [in] 参数。如果对参数进行定义,则每个参数的类型必须为基元类型。
- 此方法必须返回 void、IEnumerable<T>、IQueryable<T>、T 或基元类 (如整数或字符串)。T 必须为一个类,此类表示数据服务将公开的数据模型中的某个实体类型。若要支持查询选项(如排序、分页和筛选),服务操作方法应返回 IQueryable<T>。
- 必须用 [WebGet] 或 [WebInvoke] 属性为此方法添加批注。[WebGet] 使您能够通过使用 GET 请求调用此方法;[WebInvoke] 使您能够通过使用 PUT、POST 或 DELETE 请求调用此方法。
- 可以用 SingleResultAttribute 为服务操作添加批注,指定此方法的返回值是一个实体而不是一个实体集。这一区别确定了生成的响应序列化。例如,当使用 AtomPub 序列化时,单个资源类型实例将表示为一个 entry 元素,而单个实例集将表示为一个 feed 元素。
[WebGet]
public IQueryable<User> Users2(int minAge)
{
return this.CurrentDataSource.Users.Where(u => u.Age >= minAge);
}Data Service 通过判断 Request Accept 来决定返回格式。我们返回 JSON 结果。
{
"d": [
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(5)",
"type": "TestModel.User"
},
"Id": 5,
"Name": "user5",
"Age": 14,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(5)/UserDetail"
}
}
},
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(6)",
"type": "TestModel.User"
},
"Id": 6,
"Name": "user6",
"Age": 18,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(6)/UserDetail"
}
}
}
]
}我们还可以添加查询选项,比如排序。
http://localhost:2394/Test.svc/Users2?minAge=14&$orderby=Age%20desc
{
"d": [
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(6)",
"type": "TestModel.User"
},
"Id": 6,
"Name": "user6",
"Age": 18,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(6)/UserDetail"
}
}
},
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(5)",
"type": "TestModel.User"
},
"Id": 5,
"Name": "user5",
"Age": 14,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(5)/UserDetail"
}
}
}
]
}注意:Data Service 对 URI 中的参数和属性名称区分大小写。
2. 侦听器
所谓侦听器就是 Data Service 允许我们截获请求,并添加自定义逻辑的一种手段。通常用于添加一些附加规则或者进行访问身份验证。
[QueryInterceptor("Users")]
public Expression<Func<User, bool>> FilterUser()
{
return u => u.Name != "user1";
}当请求 http://localhost:2394/Test.svc/Users 时,我们会发现 user1 被过滤掉。这种方式很有用,比如过滤掉管理员信息。
{
"d": [
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(2)",
"type": "TestModel.User"
},
"Id": 2,
"Name": "user2",
"Age": 11,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(2)/UserDetail"
}
}
},
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(3)",
"type": "TestModel.User"
},
"Id": 3,
"Name": "user3",
"Age": 12,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(3)/UserDetail"
}
}
},
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(4)",
"type": "TestModel.User"
},
"Id": 4,
"Name": "user4",
"Age": 13,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(4)/UserDetail"
}
}
},
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(5)",
"type": "TestModel.User"
},
"Id": 5,
"Name": "user5",
"Age": 14,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(5)/UserDetail"
}
}
},
{
"__metadata": {
"uri": "http://localhost:2394/Test.svc/Users(6)",
"type": "TestModel.User"
},
"Id": 6,
"Name": "user6",
"Age": 18,
"UserDetail": {
"__deferred": {
"uri": "http://localhost:2394/Test.svc/Users(6)/UserDetail"
}
}
}
]
}我们可以用类似下面这样的方式来验证访问者信息,以便决定返回策略。
[QueryInterceptor("Users")]
public Expression<Func<User, bool>> FilterUser()
{
return u => HttpContext.Current.Request.UserHostAddress == "127.0.0.1";
}当然,实际的验证策略可能是用户身份信息。 还有就是查询侦听器不能包含参数。
另外一种侦听器是针对修改行为的。
[ChangeInterceptor("Users")]
public void OnUserChange(User user, UpdateOperations action)
{
if (action == UpdateOperations.Add && user.Name.ToLower().Contains("admin"))
throw new DataServiceException(400, "The user name is not allowed to contain 'admin' !");
}当客户端增加一个包含 "admin" 字符串的用户时,将触发异常。
[最后修改由 yuhen, 于 2009-04-29 09:53:14]
评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=807
这篇日志没有评论。









