我们有OpenRasta服务,我们希望使用媒体类型来对我们的资源进行版本控制。我们将为每个新版本提供一组不同的DTO,可通过命名空间进行区分。对于每个版本的DTO,我们都有相应的媒体类型。
所以DTO将映射到这样的媒体类型:
Namespace.Dto.V1.MyResource -> application/vnd.Namespace.Dto.V1.MyResource+json
Namespace.Dto.V2.MyResource -> application/vnd.Namespace.Dto.V2.MyResource+json
存储库实现将特定于DTO的版本,但接口是通用的。我希望我的处理程序和编解码器也是通用的,所以我不需要为每个版本的DTO复制/粘贴它们。所以我希望我的路线看起来像这样:
ResourceSpace.Has.ResourcesOfType<V1.MyResource>()
.AtUri("MyResource/{resourceID}")
.HandledBy<MyResourceHandler<Dto.V1.MyResource>>()
.TranscodedBy<MyResourceCodec<Dto.V1.MyResource>>()
.ForMediaType(mediaTypeMapper.GetMediaType(typeof(Dto.V1.MyResource)));
//V2 of DTOs
ResourceSpace.Has.ResourcesOfType<V2.MyResource>()
.AtUri("MyResource/{resourceID}")
.HandledBy<MyResourceHandler<Dto.V2.MyResource>>()
.TranscodedBy<MyResourceCodec<Dto.V2.MyResource>>()
.ForMediaType(mediaTypeMapper.GetMediaType(typeof(Dto.V2.MyResource)));
这应该有用吗?现在,似乎我的服务正在处理MyResourceHandler<Dto.V1.MyResource>
的请求,而不管GET请求中的Accept标头是什么。
有什么想法?我们可以改变我们的方案以使用/v1/MyResource/
之类的URI而不是使用accept标头,但是这样做会很好。
修改 我应该补充一点,我们使用媒体类型进行版本控制的部分原因是因为这是一项供内部使用的服务,不能在公共网站上访问。
答案 0 :(得分:1)
您在同一个URI上注册了两种资源类型,只有一种会被选中,在请求时无法区分。
我不认为URI或媒体类型中的版本控制在网络上是个好主意。也就是说,根据您的需要(不同的媒体类型),然后使用相同的资源类型并使用您的编解码器从传入/传出数据填充相同的类型。这是OR中编解码器的责任,在DTO和媒体类型格式之间建立联结。
在传入的请求中,我们需要根据URI知道您想要的资源类型。如果你有两种不同的类型,它应该是不同的资源。如果您执行以下操作,那么表示::
ResourceSpace.Has.ResourcesNamed("myResource").AtUri("/myResource").HandledBy<ResourceV1Handler>().And.HandledBy<ResourceV2Handler>();
ResourceSpace.Has.ResourcesOfType<MyV1Resource>().WithoutUri.TranscodedBy<V1Codec>();
ResourceSpace.Has.ResourcesOfType<MyV2Resource>().WithoutUri.TranscodedBy<V2Codec>();
然后你可以写
public class handler {
public object Post(MyV1Resource resource) {}
public object Post(MyV2Resource resource) {}
}
那就行了。你将无法做到的是以这种方式实现get,因为OR在大多数情况下假设一个资源类型==一个URI。
对于泛型,如果使用IoC容器,则可以以通用方式注册处理程序(也称为typeof(IHandler&lt;&gt;),类型为(Handler&lt;&gt;))。这意味着任何IHandler都将被解析为Handler。然后,您只需在注册中注册HandledBy&gt;()就可以了。同样适用于编解码器(但同样,OR中的编解码器用于处理媒体类型问题,而不仅仅是序列化机制,因为序列化本身对于Web来说是邪恶的,应该很少使用)。