I have a simple REST service built with ServiceStack.
If I configure the routes like this:
//register user-defined REST-ful urls
Routes
.Add<Contact>("/Contacts")
.Add<Contact>("/Contacts/{ContactId}")
This request succeeds.
http://<server>:59557/Contacts?ContactId=9999 //Works
If I configure the routes like this (Business Analyst prefers the generated metadata)
//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
How can I configure the routes in the second sample so that a request to /Contacts?ContactId=9999 will succeed?
Thanks.
Some of the Routing in ServiceStack is explained on the Your first website explained wiki page:
[Route("/hello/{Name}")]
only matches:
/hello/name
where as:
[Route("/hello")]
matches:
/hello?Name=XXX
Note: The QueryString, FormData and HTTP Request Body isn't a part of the Route (i.e. only the /path/info is) but they can all be used in addition to every web service call to further populate the Request DTO.
and using a route with a wild card path like:
[Route("/hello/{Name*}")]
matches:
/hello
/hello/name
/hello/my/name/is/ServiceStack
Another good use-case for when to use wildcard routes.
So to match /Customers?Key=Value
and /Customers/{Id}
you need to register matching routes for both these routes, e.g:
Routes
.Add<GetContact>("/Contacts", "GET")
.Add<GetContact>("/Contacts/{ContactId}", "GET")
Also related to this is registering Auto routes via the AddFromAssembly extension method, where this single call:
Routes.AddFromAssembly(typeof(MyService).Assembly)
Goes through and scands all your services (in the Assemblies specified) and registers convention-based routes based on all the HTTP methods you have implemented. E.g. if your GetContact
and UpdateContact
services had Id
properties it would automatically register the following routes:
Routes
.Add<GetContact>("/Contacts", "GET")
.Add<GetContact>("/Contacts/{Id}", "GET")
.Add<UpdateContact>("/Contacts", "POST PUT")
.Add<UpdateContact>("/Contacts/{Id}", "POST PUT")
And if you just had a single Contacts
REST Service with implementations for all the HTTP Verbs it would register these routes:
Routes
.Add<Contacts>("/Contacts", "GET POST PUT DELETE PATCH")
.Add<Contacts>("/Contacts/{Id}", "GET POST PUT DELETE PATCH")
This is described in more detail on the New API Design wiki but the weighting used to select a route is based on:
See the Smart Routing section on the wiki for examples.
Since Routing in MVC can be slow when you have a large number of Routes, I think it's worthwhile pointing out ServiceStack's Routing implementation is implemented with hash lookups and so doesn't suffer the linear performance regression issues you might have had with MVC.