簡體   English   中英

重載集合資源的后處理程序方法

[英]Overloading Post Handler Methods for a Collection Resource

我正在使用OpenRasta 2.0.3.0。

我有一個名為ListOfActivity的集合資源,以及兩種不同類型的活動, FileUploadActivityCommentActivity 這兩個活動類都從ActivityBase繼承。

如果我向ticket {ticketId] \\ activities發出GET請求,那么我會返回ListOfActivity 我希望能夠將任何一種活動發布到相同的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)對這個問題的回答似乎表明它應該是可能的。

你不能那樣做,那簡直就是邪惡。

絕對不要在資源注冊之間重用URI,否則,URI將會非常混亂,並且不再能夠做出邏輯決定(我們應該在這些條件下添加一些警告/錯誤)。

我首先用資源是聲明資源類型。 這是“活動列表”,因此我們將使用

ResourceSpace.Has
  .ResourcesOfType<ListOfActivity>()
  .AtUri("tickets/{ticketId}/activities")
  .HandledBy<ActivityHandler>()
  .AsXmlSerializer();

當OpenRasta查看您的方法時,它將嘗試找到可以將類型反序列化為正確類型的內容。 在這里,由於它們共享一個基類,而OpenRasta是一個非常酷的框架,您只需要將類型本身與資源相關聯,而無需為其指定標識符(URI)。

ResourceSpace.Has
  .ResourcesOfType<ActivityBase>()
  .WithoutUri
  .AsXmlSerializer()

現在,當您對活動列表進行POST時,或將查看您的處理程序,找到與http請求匹配的所有方法(此處為Post方法),並嘗試對每個請求中的請求進行反序列化,最后選擇該方法剩下的投入最多。

如果您了解這個概念,就會知道OR可能會嘗試對這兩種方法進行反序列化,這意味着您需要一個可搜索的請求(又名asp.net上的默認值,而不是HttpListener上的默認值)。 您至少需要意識到這一點,並且如果可能是一個問題,請獨立拆分注冊以避免這種情況(例如,具有tickets / {ticketId} / comments和... / fileUploads等)。

URI名稱用於區分一個資源的多個URI,而不是一個URI的多個資源(在OR中永遠無法使用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM