我正在使用OpenRasta 2.0.3.0。
我有一个名为ListOfActivity
的集合资源,以及两种不同类型的活动,FileUploadActivity
和CommentActivity
。两个活动类都继承自ActivityBase
。
如果我向 ticket {ticketId] \ activities 发出GET请求,那么我会返回ListOfActivity
。我希望能够将任何类型的活动POST到相同的URI以将项目添加到集合中,但是我无法让OpenRasta在处理程序上解析适当的方法。
我的(缩写)处理程序实现是:
public class ActivityHandler : ServiceBase, IActivityHandler
{
public ListOfActivityResource GetByTicketId(int ticketId)
{
...
}
public OperationResult Post(FileUploadActivity fileUploadActivity, int ticketId)
{
...
}
public OperationResult Post(CommentActivity commentActivity, int ticketId)
{
...
}
}
以下是资源类:
[XmlType(TypeName = "commentActivity")]
public class CommentActivity : ActivityBase
{
[XmlElement("comment")]
public string Comment { get; set; }
}
[XmlType(TypeName = "fileUploadActivity")]
public class FileUploadActivity : ActivityBase
{
[XmlElement("content")]
public string Content { get; set; }
}
public class ActivityBase
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlElement("when")]
public DateTime When { get; set; }
[XmlElement("who")]
public string Who { get; set; }
// this property name is purposefully not called 'TicketId' as it caused an
// issue with OpenRasta's magic URI <> method matching algorithm because the
// UriTemplate for activity resources contains a parameter of the same name
[XmlElement("ticketId")]
public int TicketIdValue { get; set; }
}
[XmlType(TypeName = "activities")]
[UriTemplate("tickets/{ticketId}/activities")]
public class ListOfActivity
{
public ListOfActivity()
{
this.Activities = new List<ActivityBase>();
}
[XmlElement("fileUpload", typeof(FileUploadActivity))]
[XmlElement("comment", typeof(CommentActivity))]
public List<ActivityBase> Activities { get; set; }
}
我的配置片段是:
ResourceSpace.Has
.ResourcesOfType<ListOfActivity>()
.AtUri("tickets/{ticketId}/activities")
.HandledBy<ActivityHandler>()
.AsXmlSerializer();
ResourceSpace.Has
.ResourcesOfType<FileUploadActivity>()
.AtUri("tickets/{ticketId}/activities")
.HandledBy<ActivityHandler>()
.AsXmlSerializer();
ResourceSpace.Has
.ResourcesOfType<CommentActivity>()
.AtUri("tickets/{ticketId}/activities")
.HandledBy<ActivityHandler>()
.AsXmlSerializer();
当我尝试发布CommentActivity
时,我收到405响应。这是我在日志中看到的内容:
Found 2 operation(s) with a matching name.
Found 0 operation(s) with matching [HttpOperation] attribute.
Operation ActivityHandler::Post(FileUploadActivity fileUploadActivity, Int32 ticketId) selected with 2 required members and 0 optional members, with codec XmlSerializerCodec with score 1.
Operation ActivityHandler::Post(FileUploadActivity fileUploadActivity, Int32 ticketId) selected with 2 required members and 0 optional members, with codec XmlSerializerCodec with score 1.
Operation ActivityHandler::Post(FileUploadActivity fileUploadActivity, Int32 ticketId) selected with 2 required members and 0 optional members, with codec XmlSerializerCodec with score 1.
Operation ActivityHandler::Post(CommentActivity commentActivity, Int32 ticketId) selected with 2 required members and 0 optional members, with codec XmlSerializerCodec with score 1.
Operation ActivityHandler::Post(CommentActivity commentActivity, Int32 ticketId) selected with 2 required members and 0 optional members, with codec XmlSerializerCodec with score 1.
Operation ActivityHandler::Post(CommentActivity commentActivity, Int32 ticketId) selected with 2 required members and 0 optional members, with codec XmlSerializerCodec with score 1.
Executing OperationResult OperationResult: type=MethodNotAllowed, statusCode=405.
No response codec was searched for. The response entity is null or a response codec is already set.
There was no response entity, not rendering.
Writing http headers.
我尝试过命名URI,并使用HttpOperationAttribute
,但它不起作用(因为我有点怀疑,因为它们都是相同的URI)。
在引入第二个活动资源之前,单个帖子方法正在妥善解决。
我在这里做错了吗? Sebastien Lambla对this question的回答似乎表明它应该是可能的。
答案 0 :(得分:0)
你不能这样做,那只是简单的邪恶。
URI永远不应该在资源注册中重复使用,或者被它非常混淆,不能再做出逻辑决策了(我们应该在这些条件上添加一些警告/错误)。
我首先使用资源声明资源类型。这是“活动列表”,因此我们将使用 。
ResourceSpace.Has
.ResourcesOfType<ListOfActivity>()
.AtUri("tickets/{ticketId}/activities")
.HandledBy<ActivityHandler>()
.AsXmlSerializer();
当OpenRasta查看您的方法时,它会尝试找到可以将类型反序列化为正确类型的内容。在这里,由于他们共享一个基类而OpenRasta是一个非常酷的框架,你只需要将类型本身与资源相关联,而不给它们自己的标识符(uris)。
ResourceSpace.Has
.ResourcesOfType<ActivityBase>()
.WithoutUri
.AsXmlSerializer()
现在,当您对活动列表进行POST时,OR会查看您的处理程序,查找与http请求匹配的所有方法(此处为Post请求),并尝试在每个方法中反序列化请求,最后选择剩余输入最多的方法。
如果您理解了这个概念,您就会知道这意味着OR可能会尝试对这两种方法进行反序列化,这意味着您需要一个可搜索的请求(也就是asp.net上的默认值,而不是HttpListener上的默认值)。你需要至少知道这一点,如果它可能是一个问题,请单独拆分注册以避免这种情况(例如有ticket / {ticketId} / comments和... / fileUploads等)。
URI名称用于区分一个资源的多个URI,而不是一个URI的多个资源(永远不会在OR中工作)。