Consider an ASP.NET MVC application with two models: let's say Company
and Person
. Each company has a list of persons. Each person belongs to one company only.
If you set up the model and use Visual Studio to generate the controllers/views, you get the ability to edit the companies at /Company/{id}
etc. and the ability to edit the persons at /Person/{id}
etc.
But I want it to be such that you can only add a person inside a company, i.e. you would edit the persons at /Company/{id}/Persons/{id}
.
How can I set up this sort of routing in ASP.NET MVC 5?
EDIT:
So I did this in my routes:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "CompanyPerson",
url: "Company/{CompanyId}/Person/{PersonId}/{action}",
defaults: new { controller = "Person", action = "Index", PersonId = UrlParameter.Optional }
);
routes.MapRoute(
name: "Company",
url: "Company/{id}/{action}",
defaults: new { controller = "Company", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/",
defaults: new { controller = "Home", action = "Index" }
);
but it still isn't working. If I go to /Company/7/Person
I get an index of persons, but /Company/7/Person/Create
just gives the same index, and the "Create New" link points to /Person/Create
instead of /Company/7/Person/Create
Is there just a way to set up all the routes explicitly, like Node or most other MVC frameworks?
Multiple Routes You need to provide at least two parameters in MapRoute, route name, and URL pattern. The Defaults parameter is optional. You can register multiple custom routes with different names.
Every ASP.NET MVC application must configure (register) at least one route in the RouteConfig class and by default, the ASP.NET MVC Framework provides one default route. But you can configure as many routes as you want.
The Default route maps the first segment of a URL to a controller name, the second segment of a URL to a controller action, and the third segment to a parameter named id.
The three segments of a default route contain the Controller, Action and Id.
Well, it doesn't work the way you're thinking. The reason is that you have two different controllers, Company
and Person
. You can't call both of them at the same time.
You are going to have to decide whether you want to edit a person at the Person
controller, or edit them at the Company
controller. Personally, I'd edit the person at the person level, but that will mean your Person.Edit
method will have to take the companyId
as well as the personId
.
So you would then create a route like this:
routes.MapRoute(
"CompanyPerson", // Route name
"Company/{companyId}/Person/{personId}", // URL with parameters
new { controller = "Person", action = "Edit" } // Parameter defaults
);
Then your Person.Edit
method would look like this:
public ActionResult Edit(int companyId, int personId) {}
EDIT:
You are going to have to use constraints to do what you want.
routes.MapRoute(
name: "CompanyPerson",
url: "Company/{companyId}/Person/{personId}/{action}",
defaults: new { controller = "Person", action = "Index", PersonId = UrlParameter.Optional },
new {personId = @"\d+" }
);
However, this now means you can do /Company/7/Person/15/Create
, and that just won't make any sense. The personId
will simply get ignored.
As for why your Create Link isn't working, is because of the id being before the action. You'll also need another route.
routes.MapRoute(
name: "CompanyPerson",
url: "Company/{companyId}/Person/Create",
defaults: new { controller = "Person", action = "Create" }
);
and this
@Html.ActionLink("Create", "Person", new { companyId = Model.companyId })
It would be a lot easier if you just stuck to the Id after the action. You also need to be careful of capitalizing variable names, as these are C# variables and are case sensitive.
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