Assigning multiple routes to the same controller or action in ASP MVC 6
Having 2 route attributes at the controller level works fine in a new RC1 application:
[Produces("application/json")]
[Route("api/[controller]")]
[Route("api/old-log")]
public class LogController: Controller
{
[HttpGet]
public IActionResult GetAll()
{
return Json(new { Foo = "bar" });
}
}
Both http://localhost:62058/api/log
and http://localhost:62058/api/old-log
return the expected json. The only caveat I have seen is that you might want to set the name/order properties of the attributes in case you need to generate the url to one of those actions.
Having 2 Attributes on the action also works:
[Produces("application/json")]
public class LogController : Controller
{
[Route("api/old-log")]
[Route("api/[controller]")]
[HttpGet]
public IActionResult GetAll()
{
return Json(new { Foo = "bar" });
}
}
However you need to be careful when having a general route at the controller level and a specific action route. In these cases the route at the controller level is used as a prefix and prepended to the url (There is a nice article about this behavior here). This might get you a different set of urls than you were expecting, for example with:
[Produces("application/json")]
[Route("api/[controller]")]
public class LogController : Controller
{
[Route("api/old-log")]
[Route("")]
[HttpGet]
public IActionResult GetAll()
{
return Json(new { Foo = "bar" });
}
}
The 2 routes that your application will listen in the last case will be http://localhost:62058/api/log
and http://localhost:62058/api/log/api/old-log
since api/log
is added as prefix to all the routes defined at the action level.
Finally, another option would be to use attributes for your new routes and then use the route table in the startup class to provide specific routes that take care of the old api.
MVC 5 Multiple Routes to Same Controller
I was able to get the expected result using RouteAttribute
on the controller itself (thank you @Michael for the resources and making me take another look at the RouteAttribute), rather than conventional MapConfig
routing. As I described in my question above, I was having difficulties when attempting the Route
approach in that I was receiving 404 errors stating the "resource could not be found".
It turns out the above errors were due to the fact that my attribute routing wasn't being wired up in the correct order, which forced the conventional route to be used (e.g. Default MapConfig) over my Route attributes.
I stumbled upon this SO post which states:
You are probably combining convention based routing with attribute
routing, and you should register your areas after you map the
attribute routes.The line
AreaRegistration.RegisterAllAreas();
should be called AFTER this line:
routes.MapMvcAttributeRoutes();
When working with Areas, you must register those areas after you register the attribute routing. I was originally registering my areas in the Application_Start
method of Globas.asax.cs
, which is called before the RouteConfig.RegisterRoutes
. I moved this registration to right below my MapMvcAttributeRoutes
call in the RouteConfig.cs
file, which allowed the following route attribute on the controller to work as expected:
[RouteArea("MyArea")]
[Route("Original/{action=index}", Order = 1)]
[Route("Other/{action=index}", Order = 0)]
public class OriginalController : Controller {
...
...
public async Task<ActionResult> Index() { ... }
}
With the above in place, I can now navigate to either of the below URLs which will properly route to the "Index" action of my OriginalController
:
website.com/MyArea/Original
website.com/MyArea/Other
This works. However, I do have another action defined that choked up the attribute routing and caused the conventional Default route (defined via the MapConfig function) to be used. My action signature:
public async Task<ActionResult> Details(int id) {
...
}
The route to this action is: website.com/MyArea/Original/Details/123
, which also satisfies the default conventional route of {area}/{controller}/{action}/{id}
.
The way around this was to go a step further with defining route attributes at the action level:
[Route("Original/Details/{id:int}")]
[Route("Other/Details/{id:int}")]
public async Task<ActionResult> Details(int id) {
...
}
Now my Route Attributes are found first, then the conventional route is used.
Angular 5 - multiple routes same controller
const routes: Routes = [
{ path: '', redirectTo: 'route1', pathMatch: 'prefix'},
{ path: 'route/:routeId', component: StartComponent},
];
This should prevent the destruction of your component
How to group multiple routes with the same controller method?
I'm not sure why do you say that RegEx is ugly. I basically think RegEx is one of the most powerful tools.
In your case, I think the below snippet should do the job:
Route::get('user/{name}', function ($name) { // }) ->where('name', '(foo|bar|baz)');
The (foo|bar|baz)
RegExr will match any of these string: 'foo', 'bar', 'baz'. So, if you need more, just add pipe (|
) and add the needed string.
How to develop multiple get router functions under same controller and same route in expressjs/nodejs?
Express considers routes in the order you add them to the router
, so /:mid/:pNo/:pSize
is considered before /:mid/:mItemId/:pNo/:pSize
. Since the request /mitems/0/0/20
matches the not only the latter, but also the former (with :mid = 'mitems'
, :pNo = '0'
, :pSize = '0'
), it will be handled by mControllers.getM
.
Therefore, add the longer (more specific) route before the shorter (less specific) one, e.g.,
router.get("/getbyId/:mid", mControllers.getById);
router.get("/:mid/:mItemId/:pNo/:pSize", mControllers.getMItems);
router.get("/:mid/:pNo/:pSize", mControllers.getM);
The getbyId
route comes first, because the word getbyId
is more specific than the placeholder :mid
.
Use same controller for multiple routes?
Here are couple of alternatives:
Out of the three, the first one i.e., Using scope as "/"
would create the exact same routes as the ones created by the routes defined in the question
.
1. Using scope as "/"
scope "/", controller: :pages do
get 'jobs'
get 'contact'
get 'terms'
get 'privacy'
end
Creates routes as below:
jobs GET /jobs(.:format) pages#jobs
contact GET /contact(.:format) pages#contact
terms GET /terms(.:format) pages#terms
privacy GET /privacy(.:format) pages#privacy
2. Using Scope as "pages"
scope :pages, controller: :pages do
get 'jobs'
get 'contact'
get 'terms'
get 'privacy'
end
Creates routes as below:
jobs GET /pages/jobs(.:format) pages#jobs
contact GET /pages/contact(.:format) pages#contact
terms GET /pages/terms(.:format) pages#terms
privacy GET /pages/privacy(.:format) pages#privacy
3. Nesting routes
resources :pages do
member do
get 'jobs'
get 'contact'
get 'terms'
get 'privacy'
end
end
Creates routes as below:
jobs_page GET /pages/:id/jobs(.:format) pages#jobs
contact_page GET /pages/:id/contact(.:format) pages#contact
terms_page GET /pages/:id/terms(.:format) pages#terms
privacy_page GET /pages/:id/privacy(.:format) pages#privacy
Multiple routes assigned to one method, how to determine which route was called?
You can look at ControllerContext.RouteData
to figure out which route they used when using multiple routes for one action.
public const string MultiARoute = "multiA/{routesuffix}";
public const string MultiBRoute = "multiB/subB/{routesuffix}";
[Route(MultiARoute)]
[Route(MultiBRoute)]
public ActionResult MultiRoute(string routeSuffix)
{
var route = this.ControllerContext.RouteData.Route as Route;
string whatAmI = string.Empty;
if (route.Url == MultiARoute)
{
whatAmI = "A";
}
else
{
whatAmI = "B";
}
return View();
}
Multiple routes to same controller
You can try something like this
public function show(Category $category, Discussion $discussion)
If you are calling localhost/forum/categories/{categories}/discussions/{discussions}
then both variables have their exact values. If you call localhost/forum/discussions/{discussions}
then Category will be just new Category
Make sure you will bind the values in your RouteServiceProvider as
$router->model('discussions', 'App\Discussion');
$router->model('categories', 'App\Category');
Related Topics
How to Increment an Integer in Ruby
Have a Parent Class's Method Access the Subclass's Constants
How to Completely Remove Webpack and All Its Dependencies from Rails App
Colon in the Front: Yaml Syntax
Generating Sequential Numbers in Multi-User Saas Application
Rails Include Only Selected Columns from Relation
How to Run Ruby in Haml in JavaScript Definition
How to Do Complex Querying with Logical Operations by Using Searchkick
Using Authlogic_API for Rails Rest API Access
How to Host a Rails Web Application
Invalid Configuration or No Rubies Listed
Ruby Rake Load Tasks from a Gem
Rails 3/ Git/ Bundler Fatal Could Not Parse Object
Made a Mistake Installing Rvm with Sudo. How to Reverse
What Is The Logic Behind This Result
Jekyll Templates Using Django-Like Liquid Blocks/Inheritance