Reputation: 21476
I have 2 endpoints built by ServiceStack services:
DELETE: /parents/{parentId}
to delete a parent, along with all its childrenDELETE: /parents/{parentId}/children/{childId}
to delete a child for the selected parent[Api("Delete a parent")]
[Tag("Parent")]
[Route("/parents/{parentId}", HttpMethods.Delete)]
public class DeleteParentRequest : IReturnVoid
{
[ApiMember(ParameterType = "path", IsRequired = true)]
public int ParentId { get; set; }
}
[Authenticate]
public class ParentService : Service
{
...
public void Delete(DeleteParentRequest request)
{
// Logic to delete parent, along with all its children
}
}
[Api("Delete a parent child")]
[Tag("Parent Child")]
[Route("/parents/{parentId}/children/{childId}", HttpMethods.Delete)]
public class DeleteParentChildRequest : IReturnVoid
{
[ApiMember(ParamterType = "path", IsRequired = true)]
public int ParentId { get; set; }
[ApiMember(ParameterType = "path", IsRequired = true)]
public int ChildId { get; set; }
}
[Authenticate]
public class ParentChildService : Service
{
...
public void Delete(DeleteParentChildRequest request)
{
// Delete the parent child
}
}
These 2 endpoints are working as expected.
Unfortunately (or actually fortunately), our QA passed the wrong endpoint when testing the delete child endpoint. What he put on Postman was DELETE: /parents/children?parentId=1&other=rndString
.
What I expect when we call that wrong endpoint is that we should get a 404 not found, since it doesn't match with any of our endpoints. But surprisingly, it actually called the delete-parent endpoint DELETE: /parents/{parentId}
.
How would that happen, even I already have a matching integer property called ParentId
in the request DTO that tells ServiceStack that I am expecting an integer from the route? Does ServiceStack have its own routing constraints? Or do I have to implement myself?
Upvotes: 1
Views: 47
Reputation: 143319
There are no constraints on the Route Path itself, i.e. this definition:
[Route("/parents/{parentId}", HttpMethods.Delete)]
Will match every DELETE request that matches the route, i.e:
DELETE /parents/1
DELETE /parents/foo
You can apply routing constraints with a Custom Route Rule, e.g:
[Route("/parents/{parentId}", HttpMethods.Delete, Matches = "**/{int}")]
Will apply the built-in **/{int}
route rule to only match routes where the last segment is an integer, i.e:
DELETE /parents/1
Upvotes: 2