Issue routing default route in MVC with Attribute Routes - c#

I am trying to find out why the routing of these two sittuations are not functioing. I want to conver this rout in the Routes.config file to a route attribute. It needs to be a default, because when you just load the site, without any url entered, it needs to hit /Home/Index action.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I added this to the Home controller for the actionResult Index(), but it didn't work. Said no document loaded.
[Route]
[Route("~/", Name = "default")]
public ActionResult Index()
{
var environmentsSharedAccounts = new List<EnvironmentSharedAccountVM>();
return View(environmentsSharedAccounts);
}
Why does this now not resolve. Thanks in advance. BTW. I am finding, that the books I have read, and the examples I have seen are seeming to be more compleicated to me then I thought I guess, because this routing has been giving me issues. I think I understand it, but it doesn't work how expected. Anyways....

Try
[Route("")]
public ActionResult Index()
....
Do you have this line on WebApiConfig.cs :
config.MapHttpAttributeRoutes();
?

Related

How can I implement routing for an extended routes in the RouteConfig file without creating a route error

I implemented a logout link in an ASP.NET MVC 5 application (C#), and it works perfectly with the current routing of my application:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Login", id = UrlParameter.Optional });
When I log in, I see the logout button and it works seamlessly.
However, I have other areas of the app that are designated for registered users (for which I have not considered the routing), and after going to an area designed for authorized users and I attempt to log out, I get the following path returned when the browser displays an error:
/Managers/Home/LogOff
I have a home controller with an action link of Logoff, but I'm uncertain how to represent my Managers folder (along with others on that level). And I could not find (and really, I have not searched exhaustively) readily available documentation of routing beyond what I implement in my routes.MapRoute file (seen above). I would appreciate it if someone can steer me in the right direction or tell me the correct pattern to use. I can't imagine the issue being anything other than routing. Thanks!
RouteConfig.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace HRCoreUS
{
using System.Web.UI.WebControls;
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Login", id = UrlParameter.Optional });
}
}
}
I see two options for you to define a route that suits you.
Fist one, if you want to log off all users from a specific folder, you can use a route like the following one. The keyword 'allusers' prevents you to have a conflict with your Default route. This also make your route more 'readable'.
config.Routes.MapHttpRoute(
"LogOffAllUserFromFolder",
"{controller}/{action}/allusers/{folder}",
new { controller = "Home", action = "Logoff", folder = RouteParameter.Optional });
This endpoint would then looks like :
/home/logoff/allusers/Managers
Second one, if you want to log off a specific user (for example user with id 124) from a 'Managers' folder, you can try the following route that won't conflict with Default since there are 4 arguments
config.Routes.MapHttpRoute(
"LogOffSpecificUserFromFolder",
"{controller}/{action}/{id}/{folder}",
new { controller = "Home", action = "Logoff", id = RouteParameter.Optional, folder = RouteParameter.Optional },
new { id = #"\d+" });
The endpoint would then looks like
/home/logoff/124/Managers
As you're id is an int I suppose, you can tell it by adding that to your route definition
new { id = #"\d+" }
And as {folder} is a string you don't need any other definition as it is the default type.
If I missunderstand your point, I hope this will gives you tips on how to declare MVC routes.
Take care.
If you want to use Attribute routing inside your Controllers folder Simply create a ManagersController
[RoutePrefix("managers")]
public class ManagerController
Then simply add a [Route("")] attribute on every function inside the controller.
Depending on any URL parameters you need define them in the Route attribute.
[HttpGet, Route("logoff}")]
public HttpResponseMessage LogOff() //route would be Managers/logoff
[HttpGet, Route("{id:int/view-profile}")]
public HttpResponseMessage ViewProfile(int id) //route would be Managers/4/view-profile
[HttpPost, Route("{id:guid/save-profile}")]
public HttpResponseMessage ViewProfile(Guid id) //route would be Managers/405750C8-0B3F-4EF2-A2A2-17A1EFBCDA39/save-profile
More info on attributes -
https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/
or for general catchall maproute in Routeconfig you would want something like this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
Make sure this is the last route defined in your RouteConfig.
Then inside a ManagersController.cs create a
public HttpResponseMessage LogOff()
This Route would be localhost.com/managers/logoff
But from how I interpreted your question it seems as if your Authentication logic is tied to a specific controller (Home)? You should have all that logic encapsulated in something like a AuthenticationController which could handle your login / logoff logic. This way its not dependent on anything else and you could have a route like this:
routes.MapRoute(
name: "Authentication",
url: "authentication/{action}",
defaults: new { controller = "Authentication", action = "Index"}
);
with a Login / LogOff Function. These would route to /authentication/login and /authentication/logoff

MVC not routing to only one of my Controller's Action Result?

I have a really weird one to me that I can't figure out. I'm not an expert with routing but this should be straight forward.
I have a controller called NewsletterController and it has the typical Index ActionResult. If I run my site in debug mode and use a link to go to my Newsletter section I get a 403.14 Forbidden message. If I add the "Index" to the route then it will go to the ActionResult just fine. I have other controllers setup with a Index ActionResult the exact same way and work just fine. It's something about this specific controller that is not working and I just don't see what the problem is.
This is my controller code:
public class NewsletterController : Controller
{
public ActionResult Index()
{
var vm = new NewsletterViewModel();
...CODE REMOVED FOR SPACE
return View(vm);
}
}
This is the action link from my _Layout.cshtml:
#Html.ActionLink("Newsletters", "Index", "Newsletter", null, new { #class = "nav-link" })
My Routing class
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
If I go here I get the 403.14 Forbidden message.
http://localhost:59571/Newsletter/
If I add the Index to the route it goes to the page.
http://localhost:59571/Newsletter/index
403.14 Forbidden typically occurs when you try to browse to a directory on the site and the Web site does not have the Directory Browsing feature enabled, and the default document is not configured.
In this case you have an actual Newsletter folder which is conflicting with the default route of the NewsletterController when you try to call
http://localhost:59571/Newsletter/
It will try to return the actual content of that folder which will fail if the feature is not enabled.
Either remove or rename the folder to something that does not conflict with any of your controller names

Another default MapRoute

In my website, I have the following default route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
When I access the Index page from the Home controller, I get the following address:
http://localhost/MyWebsite/
Everything is okay, however, I would like to add another default route for the following Controller and Page:
http://localhost/MyWebsite/Profile/Index/8
For the link above, I would like to have the following route:
http://localhost/MyWebsite/Profile/8
Without showing the "Index" page name.
How is it possible?
Inside the RouteConfig, set enable to route Actions via Attribute:
routes.MapMvcAttributeRoutes();
After that, add the Attribute Route above the Action name:
[Route("Perfil/{id}")]
public ActionResult Index(int? id)
{
return View();
}

Poor Performance And Slow Website With MVC 5 Attribute Routing

I am developing a website on Azure, with mvc5. I use attribute routing, with routes and route prefix on controllers. I call with action.link helper. I did not name my routes.
I did the following on my route.config:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.LowercaseUrls = true;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
My controllers are like:
[OutputCache(Duration = 600, Location = System.Web.UI.OutputCacheLocation.Client)]
[RoutePrefix("istanbul/kadikoy")]
[Route("{action=index}")]
public class KadikoyController : Controller
{
public ActionResult Index()
{
return View();
}
[Route("kadikoy-tarihi")]
public ActionResult KadikoyTarihi()
I have very very poor performance as server response time, i.e. 9.6s
If I comment out the attribute route codes, with default routing, I have 2.1 s server response time.
Thank you for your replies.
It turns out that the really expensive bit of this operation isn't mapping your attributed routes, it's that before that can happen MVC needs to create the ControllerFactory and retrieve all the Controller types. That process accounts for 1245 ms in my project, while the rest of the MapMvcAttributeRoutes() functions take about 45ms. My guess is that if you don't use the attribute routing the controllers are found as needed rather than all at once.

Removing /Index from end of browser URL

I'm a bit rusty on my MVC routing.
I'm using a default route of
routes.MapRoute(
"Default",
"{controller}/{action}",
new
{
controller = "Default",
action = "Index",
});
I have a controller:
public class SomeController : Controller
{
public async Task<ActionResult> Index()
So, typically, this can be hit with either http://mydomain/Some/Index -or- http://mydomain/Some
On this particular controller, I'd like to either deny (404) ~/Some/Index or simply redirect ~/Some/Index to ~/Some.
This is relatively easy to accomplish in the controller:
public async Task<ActionResult> Index()
{
var p = Request.Url.Segments;
var last = p.Last();
if(string.Equals(last, "index", StringComparison.InvariantCultureIgnoreCase))
{
return RedirectToActionPermanent("Index");
}
but now it seems like the controller is getting polluted by cross-cutting concerns. Is there a cleaner way?
Yes there are much cleaner ways -
Option 1 - You can use HTtpModule for Permanant redirection
Option 2 - Use UrlRewriter
Option 3 - You can also implement an Action Filter in which you can redirect
So, if I add another route above the default route that dumps this specific url onto a non-existent controller/action, then I get a lovely 404. Perfect.
routes.MapRoute(
"SomeIndexDeny",
"Some/Index",
new
{
controller = "NonExistentController",
action = "NonExistentMethod"
});
routes.MapRoute(
"Default",
"{controller}/{action}",
new
{
controller = "Default",
action = "Index",
});

Categories

Resources