Подтвердить что ты не робот

ServiceStack Routing не работает с querystring

У меня есть простая служба REST, построенная с ServiceStack.

Если я настраиваю маршруты следующим образом:

        //register user-defined REST-ful urls
        Routes
            .Add<Contact>("/Contacts")
            .Add<Contact>("/Contacts/{ContactId}")

Этот запрос успешно завершен.

http://<server>:59557/Contacts?ContactId=9999 //Works

Если я настрою такие маршруты (Business Analyst предпочитает сгенерированные метаданные)

        //register user-defined REST-ful urls
        Routes
            .Add<UpdateContact>("/UpdateContact", "PUT")
            .Add<CreateContact>("/CreateContact", "POST")
            .Add<GetContact>("/Contacts/{ContactId}", "GET")

http://<server>:59557/Contacts/9999           //Works
http://<server>:59557/Contacts?ContactId=9999 //Fails, Handler for request not found

Как настроить маршруты во втором образце, чтобы запрос/Контакты? ContactId = 9999 будет успешным?

Спасибо.

4b9b3361

Ответ 1

Часть маршрутизации в ServiceStack объясняется на Ваш первый сайт объяснил wiki:

[Route("/hello/{Name}")]

соответствует только:

/hello/name

где as:

[Route("/hello")]

соответствует:

/hello?Name=XXX

Примечание. Тело запроса QueryString, FormData и HTTP не является частью маршрута (т.е. только путь/путь/информация), но все они могут использоваться в дополнение к каждому вызову веб-службы для дальнейшего заполнения запроса DTO.

и используя маршрут с логическим путем, например:

[Route("/hello/{Name*}")]

матчи:

/hello
/hello/name
/hello/my/name/is/ServiceStack

Еще один хороший вариант использования карт подстановочных знаков.

Поэтому для соответствия /Customers?Key=Value и /Customers/{Id} вам необходимо зарегистрировать соответствующие маршруты для обоих этих маршрутов, например:

Routes
    .Add<GetContact>("/Contacts", "GET")
    .Add<GetContact>("/Contacts/{ContactId}", "GET")

Как авторизовать маршруты на основе протоколов для всех служб

Кроме того, это связано с регистрацией Auto-маршрутов с помощью метода расширения AddFromAssembly, где этот единственный вызов:

Routes.AddFromAssembly(typeof(MyService).Assembly)

Проходит и сканирует все ваши сервисы (в указанных сборках) и регистрирует маршруты на основе протоколов на основе всех методов HTTP, которые вы реализовали. Например. если ваши службы GetContact и UpdateContact имели свойства Id, они автоматически регистрировали следующие маршруты:

Routes
    .Add<GetContact>("/Contacts", "GET")
    .Add<GetContact>("/Contacts/{Id}", "GET")
    .Add<UpdateContact>("/Contacts", "POST PUT")
    .Add<UpdateContact>("/Contacts/{Id}", "POST PUT")

И если бы у вас была только одна служба Contacts REST с реализациями для всех HTTP-глаголов, она зарегистрировала бы эти маршруты:

Routes
    .Add<Contacts>("/Contacts", "GET POST PUT DELETE PATCH")
    .Add<Contacts>("/Contacts/{Id}", "GET POST PUT DELETE PATCH")

Порядок разрешения маршрутизации

Это более подробно описано в New API Design wiki, но взвешивание, используемое для выбора маршрута, основано на:

  • Сначала используются любые точные буквенные соответствия
  • Точное совпадение глагола предпочтительнее всех глаголов
  • Чем больше переменных на вашем маршруте, тем меньше у него
  • Когда Маршруты имеют одинаковый вес, порядок определяется положением действия в службе или орденом регистрации (FIFO)

См. раздел Smart Routing в вики для примеров.

Отличная производительность

Поскольку Маршрутизация в MVC может быть медленной, когда у вас есть большое количество Маршрутов, я думаю, что стоит отметить, что реализация ServiceStack Routing реализована с хэш-поисками и поэтому не страдает от линейных проблем с регрессией производительности, которые могли возникнуть с MVC.

Ответ 2

После fooobar.com/info/306392/... вы можете попробовать этот маршрут:

/Contacts/{Ids*}

и используйте этот класс запроса:

public class ContactRequest { public string Ids { get; set; } }

Затем, учитывая URL <service>/Contacts?Id=1&Id=2&Id=3, ServiceStack заполнит свойство Ids объекта запроса следующей строкой:

Id=1&Id=2&Id=3

чтобы затем вы могли проанализировать список идентификаторов, например

public object Get(ContactRequest request)
{
    var idPairs = request.Ids.Split("&");
    var ids = new List<string>();
    foreach (var idPair in idPairs)
    {
        ids.Add(idPair.Split("=")[1];
    }
    // ... do something with your ids now ...
    // ... return results ...
}

Конечно, вы также можете обернуть всю логику синтаксического анализа в блоке try...catch для обработки стробированных строк запроса.