我正在编写一个REST服务,它处理存储在数据库中的SomeKindOfResource
。
不要问我为什么(不要!)但由于某些原因,相应的基础表具有可变数量的列。这是它的方式,我无法改变它。
因此,当我发出GET /SomeKindOfResources/{id}
时,我的DTO(稍后序列化为JSON)可能包含可变数量的“字段”。我知道如何处理动态对象/序列化部分。我的问题更多的是关于事物的哲学方面。
假设我的客户想要知道调用GET /SomeKindOfResources/{id}
所返回的字段列表是什么,例如,该列表确定了可以在以后使用的过滤器列表SomeKindOfResources
。基本上,我需要类似“GetCapability”的东西。
您将如何以RESTful方式处理此类场景?
答案 0 :(得分:4)
如果我正确理解您的要求,您希望为具有动态字段的特定对象(即通过Id)返回元数据(如)响应,因此您的客户端知道它将在接收时收到的字段类型请求该对象。
请注意:动态DTO不是RESTful。 DTO的重点是它是一份商定的合同。它不应该更改,因此没有RESTful规则来处理您的用例。
如果您要实现这一点,这些是三种可能的方法。
在您的服务中创建新路由,因为标准ServiceStack MetadataFeature
未涵盖此方案,因为它仅适用于静态DTO。所以创建这样的东西:
[Route("/SomeKindOfResources/{Id}/metadata", "GET"]
然后,您希望对该路由的响应向您的客户端描述字段。这是阴天的地方。 MetaDataFeature
使用XSD来描述您的标准DTO,您可以根据您对可用字段的数据库查找,编写您的操作以生成描述您的字段的XSD响应。但是,您的客户会知道如何解析XSD吗?由于您的使用不是标准的,并且不能期望客户端以RESTful方式处理它,因此您可能只想使用简单的响应类型,例如基本上只返回字段名称的Dictionary<string,Type>()
,以及基础类型。这适用于简单的内置类型,例如string
,int
,bool
等,但自定义类方案将更难处理,例如List<MySpecialType>
。
伪客户端代码:
var fieldMetaData = client.get("/SomeKindOfResources/123/metadata");
var result = client.get("/SomeKingOfResources/123");
Example XSD Metadata Response.
但是,根据RFC2616 §9的建议,您可能希望考虑使用OPTIONS
动词而非GET
请求添加到/metadata
前面的另一个请求。
此方法允许客户端确定与资源相关联的选项和/或要求,而不会暗示资源操作或启动资源检索。
伪客户端代码:
var fieldMetaData = client.options("/SomeKindOfResources/123");
var result = client.get("/SomeKindOfResources/123");
但请记住,REST中的OPTIONS
通常用于设置CORS。
当ServiceStack返回JSON时,您可以告诉ServiceStack.Text序列化程序在属性调用__type
中包含返回类型信息。虽然这对您的客户来说可能并不容易解释,并且它也全局适用于所有JSON响应,因此不仅限于该操作。在您的配置方法中添加:
JsConfig.IncludeTypeInfo = true;
伪客户端代码:
var result = client.get("/SomeKingOfResources/123");
var typeInformation = result.__type;