Перегрузка методов обработчика записей для ресурса коллекции - PullRequest
0 голосов
/ 14 февраля 2012

Я использую OpenRasta 2.0.3.0.

У меня есть ресурс коллекции под названием ListOfActivity и два различных типа действий, FileUploadActivity и CommentActivity. Оба класса активности наследуются от ActivityBase.

Если я отправлю запрос GET на tickets {ticketId] \ деятельность , тогда я получу обратно 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).

До введения второго ресурса деятельности метод единой записи разрешался в порядке.

Я что-то здесь не так делаю? Ответ Себастьяна Ламблы на этот вопрос может показаться, что это возможно.

1 Ответ

0 голосов
/ 14 февраля 2012

Вы не можете этого сделать, это просто зло.

Никогда не следует повторно использовать URI при регистрации ресурсов, ИЛИ ужасно смущается этим и больше не может принимать логические решения (мы должны добавить некоторыепредупреждение / ошибка в этих условиях).

Сначала я объявил бы тип ресурса с указанием ресурса.Здесь это «список действий», поэтому мы будем использовать , что .

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

Когда OpenRasta рассмотрит ваши методы, он попытается найти что-то, что может десериализоватьвводит правильный тип.Здесь, поскольку они совместно используют базовый класс, а OpenRasta - действительно классная среда, вам просто нужно связать сами типы с ресурсами, не давая им свой собственный идентификатор (uris).

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

Теперь, когда высделайте POST для списка действий, ИЛИ посмотрите на ваш обработчик, найдите все методы, которые соответствуют http-запросу (здесь Post), и попробуйте десериализовать запрос в каждом из них, и, наконец, выбрали метод с наибольшим количествомоставшиеся входные данные.

Если вы понимаете эту концепцию, вы будете знать, что это означает, что ИЛИ может попытаться десериализовать оба метода, что означает, что вам нужен запрос, который можно искать (по умолчанию на asp.net, а непо умолчанию на HttpListener).Вы должны знать об этом как минимум, и, если это может быть проблемой, разделите регистрации независимо, чтобы избежать этого (например, наличие билетов / {ticketId} / comments и ... / fileUploads или тому подобное).

Имена URI предназначены для различения нескольких URI для одного ресурса, а не нескольких ресурсов для одного URI (который никогда не будет работать в OR).

...