My project is multilingual and also has routing, but I need to allow hyphens in the URLs, such as: example.com/en/our-team.
In this website (http://www.bousie.co.uk/blog/allow-dashes-within-urls-using-asp-net-mvc4/) I found a solution to this, adding the following code in Global.asax :
public class HyphenatedRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["controller"] =
requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
requestContext.RouteData.Values["action"] =
requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
return base.GetHttpHandler(requestContext);
}
}
And on RouteConfig.cs, replace this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
With this:
routes.Add(
new Route("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = "" }),
new HyphenatedRouteHandler())
);
The problem is that i don't know how to do it in my code:
using System.Web.Mvc;
using System.Web.Routing;
namespace theme_mvc
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapLocalizeRoute("Default",
url: "{culture}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { culture = "[a-zA-Z]{1}[a-zA-Z]{1}" });
routes.MapRouteToLocalizeRedirect("RedirectToLocalize",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}
}
How could i adapt my code to support hyphens (-) in the URL?
The link you have posted to uses the wrong approach. Routing is a 2-way mapping, but if you only customize the MvcRouteHandler, you are only taking into account the incoming routes.
This issue comes up so often that someone has created a hyphenated lowercase route project on GitHub, which would do what you want except you need to also combine it with the route that is being called by your MapLocalizeRoute extension method.
But since you have not posted the code for MapLocalizeRoute or MapRouteToLocalizeRedirect I can't tell you how that is done.
Related
I am trying to download a file, when I click on a hyperlink, but I always get a Resource not found exception.
The controller action never gets hit.
Index.cs.html:
#{
ViewBag.Title = "Files";
}
#Html.ActionLink("Download Report", "DownloadFile", "FileDownload", new { type = "pdf" }, new { #class = "" })
Rendered Action-Link:
http://localhost:58255/FileDownload/DownloadFile?type=pdf
When I uncomment the MapRoute entry "Files" in the routeConfig the action link is rendered like this:
http://localhost:58255/FileDownload/DownloadFile/pdf
But neither of them work! -> The resource cannot be found
Controller (Only Index action gets hit when the view loads, but nothing when I click on the actionlink):
[AllowAnonymous]
public class FileDownloadController : Controller
{
public ActionResult Index()
{
return View();
}
FilePathResult DownloadFile(string type)
{
var fn = $"~/Documents/Test.{type}";
return File(fn, "application/pdf", Server.UrlEncode(fn));
}
RegisterRoutes.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(); // for attribute routing on action
AreaRegistration.RegisterAllAreas();
//routes.MapRoute(
// name: "Files",
// url: "{controller}/{action}/{type}",
// defaults: new { controller = "FileDownload", action = "DownloadFile", type = UrlParameter.Optional }
//);
// Should be last
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
...coming from the WebForms area...
Please try to add public access modifier before action name
public FilePathResult DownloadFile(string type)
{
var fn = $"~/Documents/Test.{type}";
return File(fn, "application/pdf", Server.UrlEncode(fn));
}
How to setup route for a view to be as home page of a domain in ASP.NET MVC application which contains Areas. I need a view of a particular area to be home page. How could this be done?
I tried using the following code without any success.
public static void RegisterRoutes(RouteCollection routes) {
routes.MapRoute(
name: "Home",
url: "",
defaults: new { controller = "Home", action = "Index" },
namespaces: new string[] { "WebApp.Areas.UI.Controllers" }
);
}
In the Area folder there is a file by name AreaNameAreaRegistration deriving from AreaRegistration, it has a function RegisterArea which sets up the route.
Default route in an Area is AreaName/{controller}/{action}/{id}. Modifying this can set an area as default area. For example I set the default route as {controller}/{action} for my requirement.
public class UIAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "UI";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"UI_default",
"{controller}/{action}/{id}", //******
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
}
I want to change the default Home controller name to new Customer controller. Can somebody explain what I should do ?
Thanks for your answer
In your Global.aspx.cs there is a method like
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Here you can change the default controller name Home to Customer.
eg
new { controller = "Customer", action = "Index", id = UrlParameter.Optional }
I need urls like /controller/verb/noun/id and my action methods would be verb+noun. For example I want /home/edit/team/3 to hit the action method
public ActionResult editteam(int id){}
I have following route in my global.asax file.
routes.MapRoute(
"test",
"{controller}.mvc/{verb}/{noun}/{id}",
new { docid = "", action = "{verb}"+"{noun}", id = "" }
);
URLs correctly match the route but I don't know where should I construct the action parameter that is name of action method being called.
Try:
public class VerbNounRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
IRouteHandler handler = new MvcRouteHandler();
var vals = requestContext.RouteData.Values;
vals["action"] = (string)vals["verb"] + vals["noun"];
return handler.GetHttpHandler(requestContext);
}
}
I don't know of a way to hook it for all routes automatically, but in your case you can do it for that entry like:
routes.MapRoute(
"test",
"{controller}.mvc/{verb}/{noun}/{id}",
new { docid = "", id = "" }
).RouteHandler = new VerbNounRouteHandler();
Try the following, use this as your route:
routes.MapRoute(
"HomeVerbNounRoute",
"{controller}/{verb}/{noun}/{id}",
new { controller = "Home", action = "{verb}"+"{noun}", id = UrlParameter.Optional }
);
Then you simply put your actionresult method:
public ActionResult editteam(int id){}
Into Controllers/HomeController.cs and that will get called when a URL matches the provided route.
I have two routes mapped in my MVC application:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Project",
"{controller}/{projectid}/{action}/{id}",
new { controller = "Project", action = "Index", id = "" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
For the most part, these pose no problems, but I do strike trouble when trying to call the /Account/LogOn view. My ActionLink syntax looks like this (I've tried a couple of variations including null route values and such):
<%= Html.ActionLink("Log On", "LogOn", "Account") %>
Browsing to this view raises a 404 error ("The resource cannot be found"). Ideally I'd like to avoid a huge amount of rework, so what would be the best way to avoid these clashes?
Have you tried this variation with the literal for the controller?
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Project",
"Project/{projectid}/{action}/{id}",
new { controller = "Project", action = "Index", id = "" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
This would catch: http://localhost/Project/12 and http://localhost/Project/12/Edit and http://localhost/Project/2/View/2
But it would pass http://localhost/Account/LogOn to the second rounte. Yes?