Use Same Controller for Multiple Routes

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



Leave a reply



Submit