Poor Performance And Slow Website With MVC 5 Attribute Routing - c#

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.

Related

Why does an ASP.NET MVC route have a name?

In an ASP.NET MVC 5 web application, there is a RouteConfig class that registers many routes. In all of the examples I have seen so far, only the "Default" route has a non-empty name. The URL pattern and default route values seem to be sufficient to correctly associate any URL to the controller and action to execute. So, is there any benefit to naming a route? For debugging or logging? Just for self-documenting the code?
For example:
public class RouteConfig
{
public static void RegisterRoutes( RouteCollection routes )
{
routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );
// Most pages.
routes.MapRoute( name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "home", action = "index", id = UrlParameter.Optional }
// A special page.
// Should the route have a name?
routes.MapRoute( name: "",
url: "special",
defaults: new { controller = "special", action = "index", HttpVerbs = HttpVerbs.Get } );
}
}
The main reason to name a route is so that if you need a link to a route from somewhere in the app, you can reference the name. That way if the actual URL/path changes you don't break everywhere in the code that references that route.

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 Conventional and Attribute routing not working together

I am using conventional routing on an ASP.Net MVC project and would like to enable Attribute routing in parallel. I have created the following but I am getting a 404 on the conventional route when enabling attribute routing
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 = "Index", id = UrlParameter.Optional }
);
}
Controller
[RoutePrefix("Registration")]
public class RegistrationController : Controller
{
[HttpGet]
[Route("Add/{eventId}")]
public ActionResult Add(int eventId)
{
}
}
Calling
http://localhost/Registration/Add/1
Works, while calling
http://localhost/Registration/Add?eventId=1
No longer works and responds with 404 NotFound
Should work if you make the {eventId} template parameter optional in the route template
[RoutePrefix("Registration")]
public class RegistrationController : Controller {
//GET Registration/Add/1
//GET Registration/Add?eventId=1
[HttpGet]
[Route("Add/{eventId:int?}")]
public ActionResult Add(int eventId) {
//...
}
}
The reason the two were not working is that the route template Add/{eventId} means that the route will only match if the {eventId} is present, which is why
http://localhost/Registration/Add/1
works.
By making it (eventId) optional eventid? it will allow
http://localhost/Registration/Add
to work as the template parameter is not required. This will now allow query string ?eventId=1 to be used, which the routing table will use to match the int eventId parameter argument on the action.
http://localhost/Registration/Add?eventId=1
I also got this issue. Which MVC version are you using?
I faced this issue with MVC in asp.net core.
I think this is a flaw as if you provide Routing attribute on any action method, its conventional route is over ridden and is not longer available so you get 404 error.
For this to work, you can provide another Route attribute to your action method like this. This will work
[Route("Add/{eventId}")]
[Route("Add")]

Issue routing default route in MVC with Attribute Routes

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();
?

Home Pages in ASP.NET MVC

I'm trying out ASP.NET MVC, but, after reading a huge tutorial, I'm slightly confused. I understand how Controllers have Actions that URLs are routed to, but how do home pages work? Is the home page its own controller (e.g. "Home") that has no actions? This sounds correct, but how is it functionality implemented without Actions (no Actions means no methods that call the View Engine)?
In other words, my question is this: how are home pages implemented (in terms of Controllers and Views)? Could you please provide sample code?
"Home" page is nothing more than arbitrary Action in a specific Controller which returns a certain View
To set the "Home", page, or better worded, the default page, you need to change the routing info in the Global.asax.cs file:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AreaRegistration.RegisterAllAreas();
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "NotHome", action = "NotIndex", id = "" } // Parameter defaults
);
Notice the route definition:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "NotHome", action = "NotIndex", id = "" } // Parameter defaults
);
This route is a "catch-all" route, meaning it will take any URL and break it down to a specific controller and action and id. If none or one of the routes are defined, it will use the defaults:
new { controller = "NotHome", action = "NotIndex", id = "" }
This says "If someone visits my application, but didn't specify the controller or action, I'm going to redirect them to the NotIndex action of my NotHome controller". I purposly put "Not" to illustrate that naming conventions of "Default.aspx", "Index.html" don't apply to MVC routes.
The home page would usually equate to the default action/view on the default controller.
So you'd create, for example, a HomeController with an Index action and a corresponding view, then in your route mappings you'd create a default, catch-all route, something like this:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
It depends on what you mean by "home page". If you mean the page seen when you go to http://www.yoursite.com (with no page or Controller name) then that is the Index controller, which works like any other except you don't see the name of the controller in the URL.

Categories

Resources