Reputation: 33
Learning a lot about MapRouting and have spent WAY too much time trying to get what I need done, so I'm hoping someone can help out. :)
I'm looking to do the following:
/api/Entities/1 <- Views the details entity with id of 1 (this is a string, not int)
/api/Entities/1/Action <- Calls a particular action on the entity with the id of 1.
/api/Entities <- Views the entities set.
/api/Entities/Action <- Calls the particular action on the entities set.
The problem I'm encountering is the last one. That is currently being intercepted by the first case, as the id is a string.
Any assistance would be greatly appreciated!
Upvotes: 3
Views: 219
Reputation: 12194
A very good reference is here
Without using Attribute based routing the answer is somewhat long winded as the RPC style (Action) and Rest methods do not co-exist nicely if you are matching to the same verb. As you have noticed the GET() and DOSOMETHING() are seen as duplicate method signatures on the same controller. To get around this you could try use two controllers:
So I would recommend using attribute based routing; however, it is possible with normal methods:
Using standard routing...
Set your routes like so
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ActionDefaultApi",
routeTemplate: "api/entities/{action}/{actionId}",
defaults: new
{
//Add more as needed
action = "(|dosomething|dosomethingelse)",
actionId = RouteParameter.Optional,
controller = "EntitiesRpc"
});
Controller 1:
public class EntitiesController : ApiController
{
public string Get()
{
return "http://server/api/Entities";
}
public string Get(string id)
{
return string.Format("http://server/api/Entities/{0}", id);
}
}
Controller 2:
public class EntitiesRpcController : ApiController
{
[HttpGet]
public string DoSomething()
{
return "http://server/api/Entities/doSomething";
}
[HttpGet]
public string DoSomething(string actionId)
{
return string.Format("http://server/api/Entities/doSomething/{0}", actionId);
}
[HttpGet]
public string DoSomethingElse()
{
return "http://server/api/Entities/doSomethingelse";
}
[HttpGet]
public string DoSomethingElse(string actionId)
{
return string.Format("http://server/api/Entities/doSomethingelse/{0}", actionId);
}
}
Now assumming you used attribute based routing you could go back to one controller and use something like this:
public class EntitiesController : ApiController
{
[Get("Entities")]
public string Get()
{
return "http://server/api/Entities";
}
[Get("Entities/{id}")]
public string Get(string id)
{
return string.Format("http://server/api/Entities/{0}", id);
}
[Get("Entities/doSomething")]
public string DoSomething()
{
return "http://server/api/Entities/doSomething";
}
[Get("Entities/doSomething/{actionId}")]
public string DoSomething(string actionId)
{
return string.Format("http://server/api/Entities/doSomething/{0}", actionId);
}
[Get("Entities/doSomethingelse")]
public string DoSomethingElse()
{
return "http://server/api/Entities/doSomethingelse";
}
[Get("Entities/doSomethingelse/{actionId}")]
public string DoSomethingElse(string actionId)
{
return string.Format("http://server/api/Entities/doSomethingelse/{0}", actionId);
}
}
Upvotes: 2