Currently I have two controllers
1 - Parent Controller
2 - Child Controller
I access my Parent Controller like this
someurl\parentcontroller
Now I want to access my children controller like this
someurl\parentcontroller\1\childcontroller
This last url should return all the children of a particular parent.
I have this route currently in my global.asax file
routes.MapHttpRoute ("Route1", "{controller}/{id}", new { id = RouteParameter.Optional });
I am not sure how can I achieve my parent\id\child
hierarchy.. How should I configure my routes to achieve this? Ideas?
Configure the routes as below. The {param} is optional (use if you need):
routes.MapHttpRoute(
name: "childapi",
routeTemplate: "api/Parent/{id}/Child/{param}",
defaults: new { controller = "Child", param = RouteParameter.Optional }
);
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then call the child APi as /api/Parent/1/child The parent can be called simple as /api/Parent/
The child controller:
public class ChildController : ApiController
{
public string Get(int id)
{
//the id is id between parent/{id}/child
return "value";
}
.......
}
Since Web API 2 you can now use Route Attributes to define custom routing per Method,
[Route("api/customers/{id:guid}/orders")]
public IEnumerable<Order> GetCustomerOrders(Guid id) {
return new Order[0];
}
You also need to add following line to WebApiConfig.Register() initialization method,
config.MapHttpAttributeRoutes();
Full article, http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
I wanted to handle this in a more general way, instead of wiring up a ChildController directly with controller = "Child"
, as Abhijit Kadam did. I have several child controllers and didn't want to have to map a specific route for each one, with controller = "ChildX"
and controller = "ChildY"
over and over.
My WebApiConfig
looks like this:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ChildApi",
routeTemplate: "api/{parentController}/{parentId}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
My parent controllers are very standard, and match the default route above. A sample child controller looks like this:
public class CommentController : ApiController
{
// GET api/product/5/comment
public string Get(ParentController parentController, string parentId)
{
return "This is the comment controller with parent of "
+ parentId + ", which is a " + parentController.ToString();
}
// GET api/product/5/comment/122
public string Get(ParentController parentController, string parentId,
string id)
{
return "You are looking for comment " + id + " under parent "
+ parentId + ", which is a "
+ parentController.ToString();
}
}
public enum ParentController
{
Product
}
enum
, so I'm still having to manage parent controllers in two separate places. It could have just as easily been a string parameter, but I wanted to prevent api/crazy-non-existent-parent/5/comment/122
from working.There's probably a better solution that's even more general, but like I said, this works for me.
An option beyond using default mvc routing is to look at Attribute Routing - https://github.com/mccalltd/AttributeRouting. Although its more work, decorating individual action methods provides a ton of flexibility when you need to design complicated routes. You can also use it in conjunction with standard MVC routing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With