重载集合资源的Post处理程序方法
本文关键字:处理 程序 方法 Post 集合 资源 重载 | 更新日期: 2023-09-27 18:24:19
我使用的是OpenRasta 2.0.3.0。
我有一个名为ListOfActivity
的集合资源,以及两种不同类型的活动,FileUploadActivity
和CommentActivity
。这两个活动类都继承自ActivityBase
。
如果我向tickets{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();
当我尝试POST一个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对这个问题的回答似乎表明这应该是可能的。
你不能那样做,那简直是邪恶。
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上的默认值)。您至少需要意识到这一点,如果这可能是一个问题,请独立拆分注册以避免这种情况(例如有tickets/{ticketId}/注释和…/fileUploads等)。
URI名称用于区分一个资源的多个URI,而不是一个URI的多个资源(这在OR中永远不会起作用)。