I have code like below
[RouteArea("Client")]
public Class LoginController : Controller {
[Route("register")]
public ActionResult SignUp() {
return View();
}
}
Attribute routing unfortunately is not working in the areas :/, if I will remove "register" route for signup, it will work just for for client/signup, but with route "register" it is not working.
I have added [RouteArea()], tried with [RoutePrefix] but nothing is working correctly "Route Area" just enabled to use it with views (before that Razor couldn't find the view).
What am I doing wrong ?
Ok I HAVE FOUND THE SOLUTION.
1 Remove Area registration class from your area
2 Use this convention :
[RouteArea("Client")]
[RoutePrefix("login")]
[Route("{action}")]
public class LoginController : Controller
{
[Route("")]
// GET: Client/Login
public ActionResult Index()
{
return View();
}
[Route("register")]
// GET: client/login/register
public ActionResult SignUp()
{
return View();
}
}
Now you can use any route you want, with any prefix :)
Related
In my MVC controller, i have two action methods which are rendering View, other 6 Action Methods are either HttpGet or HttpPost. I want to do the below
for ActionMethods rendering View it will be "controller/action". But for the GET/POST, i want it to be api/whatevernameilike.
Is it acheivable in asp.net mvc core?
TIA
Worth trying as well if the previous methods aren't working:
[HttpGet("/api/whatevernameilike")]
Attribute Routing in ASP.NET Web API 2 has an example for this:
Use a tilde (~) on the method attribute to override the route prefix:
[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// GET /api/authors/1/books
[Route("~/api/authors/{authorId:int}/books")]
public IEnumerable<Book> GetByAuthor(int authorId) { ... }
// ...
}
Routing to controller actions in ASP.NET Core shows the following:
[Route("[controller]/[action]")]
public class HomeController : Controller
{
[Route("~/")]
[Route("/Home")]
[Route("~/Home/Index")]
public IActionResult Index()
{
return ControllerContext.MyDisplayRouteInfo();
}
public IActionResult About()
{
return ControllerContext.MyDisplayRouteInfo();
}
}
In the preceding code, the Index method templates must prepend / or ~/ to the route templates. Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller.
You can use route attribute on top of your controller
ex:
[Route("Api/Yourchosenname")]
public async Task<IActionResult> Action()
{
return Ok();
}
I have a couple of controllers like this:
[RoutePrefix("side-navigation")]
public class SideNavigationController : BaseController
{
[Route("{pathname}")]
public ActionResult Index(string pathname)
{
SideNavigationPopoutModel model = _sideNavFactory.Value.CreatePopout(pathname);
if (model != null)
{
return View(model);
}
return HttpNotFound();
}
}
public class CatchAllController : BaseController
{
public ActionResult Index(string pathname)
{
CatchAllModel model = _catchAllModelFactory.Value.Create(pathname);
if (model != null)
{
// TODO: Do we need this - what does it do?
// TempData.Restore(this);
return View(model);
}
return HttpNotFound();
}
}
But I cannot seem to get to my index action in the side navigation controller - if I browse to localhost/side-navigation/test it's hitting the catch all controller with side-navigation/test as it's pathname instead of the side navigation one with test as the pathname.
Can anyone see anything I am doing wrong here or how to make the side navigation controller work?
This is the route config:
// MVC attribute routing
routes.MapMvcAttributeRoutes();
// Default catch all route
routes.MapRoute(
"Default",
"{*pathname}",
new { controller = "CatchAll", action = "Index" });
Weirdly, if I change the route of the side navigation index to test/{pathname} and browse to side-navigation/test/test it will work and the controller will be hit but I don't want to add anything before the pathname
It seems that you are not using [Area] also put attribute [Route("[action]")] above method.
Ok I have fixed this by adding an asterisk before the pathname:
[RoutePrefix("side-navigation")]
public class SideNavigationController : BaseController
{
[Route("{*pathname}")]
public ActionResult Index(string pathname)
{
}
}
If anyone can explain why this works and without an asterisk doesn't, it would be greatly appreciated, as I also have a product controller set up in exactly the same way that doesn't need the asterisk
[RoutePrefix("side-navigation")]
public class SideNavigationController : BaseController
{
[Route("{*pathname}")]
public ActionResult Index(string pathname)
{
}
}
I have a weird bug using attribute routing with the following two controllers:
[Route("{action=Index}")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
[RoutePrefix("search")]
[Route("{action=Index}")]
public class SearchController : Controller
{
public ActionResult Index(string searchTerm)
{
return View();
}
}
And in the route config:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
As you can see, the second controller should have a prefix of search
However if I go to dev.local/search?searchterm=test
I get the error
The request has found the following matching controller types:
Marshalls.WebComponents.Web.Controllers.SearchController
Marshalls.WebComponents.Web.Controllers.HomeController
If I remove the [Route("{action=Index}")] from the homecontroller, it will work fine, but then I cannot get to the homepage using http://dev.local/
This hasn't happened before and usually works ok so I'm wondering if anyone can spot anything obvious I have messed up
Add RoutePrefix for HomeController and move Route from controller to methods/actions.
Empty string in Route and RoutePrefix attributes means that this controller or action is default.
http://dev.local/ => HomeController and Index action
http://dev.local/search?searchTerm=123 => SearchController and Index action
Please keep in mind that only one controller can have empty RoutePrefix and only one action in controller can have empty Route
[RoutePrefix("")]
public class HomeController : Controller
{
[Route("")]
public ActionResult Index()
{
return View();
}
}
[RoutePrefix("search")]
public class SearchController : Controller
{
[Route("")]
public ActionResult Index(string searchTerm)
{
return View();
}
}
Using attribute based routing I would like to match the following routes:
~/
~/Home
~/Home/Index
to HomeController.Index, and this route:
~/Home/Error
to HomeController.Error. Here is my configuration:
[Route("[controller]/[action]")]
public class HomeController : Controller {
[HttpGet, Route(""), Route("~/")]
public IActionResult Index() {
return View();
}
[HttpGet]
public IActionResult Error() {
return View();
}
}
I have tried adding Route("[action]"), Route("Index"), and other combinations but still don't get a match for:
/Home/Index
The empty route Route("") combines with the route on controller, use Route("/") to override it instead of combining with it:
[Route("[controller]/[action]")]
public class HomeController : Controller {
[HttpGet]
[Route("/")]
[Route("/[controller]")]
public IActionResult Index() {
return View();
}
[HttpGet]
public IActionResult Error() {
return View();
}
}
Alternatively, you can remove the /[action] on the controller, which makes it a bit easier (no need to override), but then you have to define a route on every action.
I'm assuming that you intentionally want to use attribute routing rather than conventional routing, so the above answer is what you need. However, just in case the assumption is wrong, this can be easily achieved with a simple conventional routing:
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
[Route("[controller]")]
public class HomeController : Controller
{
[Route("")] // Matches 'Home'
[Route("Index")] // Matches 'Home/Index'
public IActionResult Index(){}
[Route("Error")] // Matches 'Home/Error'
public IActionResult Error(){}
}
I'm trying to make an application that has an area where you only can get in when u are logged in.
For some reason when I redirect to my area after the login this fails. Resulting in following Route generation
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation(1, "User logged in.");
return RedirectToAction("Index", "Home", new { area = "Dashboard" });
}
Route that the redirect makes:
http://localhost:23490/Account/Login?ReturnUrl=%2FDashboard%2FHome
And if I surfto the link directly (like so) http://localhost:23490/Dashboard/Home/Index
I get an 404
The controller I'm trying to reach is defined like so
//[Authorize]
[Area("Dashboard")]
[Route("Dashboard/[controller]")]
public class HomeController : Controller
{
// GET: Dashboard
[HttpGet]
public ActionResult Index()
{
return View();
}
I checked everything I could find about this topic but as this is very new there is not much information on this.
What I have tried
Checked if view & controller are defined correctly, they are
Checked if the routing is correct, seems like it to me
app.UseMvc(routes =>
{
routes.MapRoute(name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");
routes.MapRoute(
name: "default",
template: "{controller=Route}/{action=Index}/{id?}");
});
Tried to create a custom redirect for action (which failed)
I'm hoping someone can assist me on this topic.
Thanks !
To make your example work, you should mark [HttpGet("Index")] your Index method
[Area("Dashboard")]
[Route("Dashboard/[controller]")]
public class HomeController : Controller
{
// GET: Dashboard
[HttpGet("Index")]
public ActionResult Index()
{
return View();
}
So here your HomeController work in RESTFUL way, so you could use public IActionResult Get() or [HttpPost] public IActionResult Post(). If this what you want, you could achieve it in more generic way
[Area("Dashboard")]
[Route("[area]/[controller]")]
public class HomeController : Controller
{
// GET: Dashboard
[HttpGet("Index")]
public ActionResult Index()
{
return View();
}
If you do not want RESTFUL for you dashboard you shourd remove [HttpGet("Index")] and add [action] to you controller attribute, so if would be like this
[Area("Dashboard")]
[Route("[area]/[controller]/[action]")]
public class HomeController : Controller
{
// GET: Dashboard
public ActionResult Index()
{
return View();
}
If this suite your purposes you can omit [Route("[area]/[controller]/[action]")] entirely because this is default convention.