MVC mapping routes to navigation menu and avoiding hard-coding links - asp.net-mvc

I have setup my routes so that I have the following flat URL structure:
mywebsite/service-option-one (goes to Home Controller, Option1 action)
mywebsite/service-option-two (goes to Home Controller, Option2 action)
mywebsite/ (goes to Home Controller, Index)
mywebsite/about (goes to Home Controller, Index with path=about)
mywebsite/contact (goes to Home Controller, Index with path=contact)
This is important as I have a lot of content views and do not want to have individual actions for these generic information pages, the simple code for the resolving the view is at the end of this post.
When building the menu the MVC Html.ActionLink helpers, but they give the incorrect addresses for generic content which makes sense as these actions do not exist!
Given my address scheme, how can is there a helper method I can use to set my anchor link targets or do i just have to resort to hard coding in html (i.e. <a href="~/contact>Contact us</a>)?
// note that the order of the routes is very important!
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// error route
routes.MapRoute(
"Error", // Route name
"Oops", // URL with parameters
new { controller = "Home", action = "Error" }
);
routes.MapRoute(
"Service1",
"service-option-one",
new { controller = "Home", action = "Option1" }
);
routes.MapRoute(
"Service2",
"service-option-two",
new { controller = "Home", action = "Option1" }
);
// default home controller route for general site content (/content), uses default path value set to Index
routes.MapRoute(
name: "Catchall",
url: "{path}",
defaults: new { controller = "Home", action = "Index", path = "Index" }
);
// home page route, blank url (/)
routes.MapRoute(
"HomePage", // Route name
"", // URL with parameters
new { controller = "Home", action = "Index" }
);
// default route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "{controller}", action = "{action}", id = UrlParameter.Optional } // Parameter defaults
);
}
public class HomeController : Controller
{
private bool ViewExists(string name)
{
ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);
return (result.View != null);
}
public ActionResult Index(string path)
{
System.Diagnostics.Debug.WriteLine("looking for..." + path);
if (ViewExists(path)==true)
{
System.Diagnostics.Debug.WriteLine("general controller action...");
return View(path);
}
else
{
System.Diagnostics.Debug.WriteLine("page not found...");
return RedirectToRoute("Error");
}
}
public ActionResult Error()
{
return View();
}
public ActionResult Option1()
{
return View();
}
public ActionResult Option2()
{
return View();
}
}

You're approaching the use of the ActionLink helper from the opposite position that you should be when using helpers. You're trying to tell Razor what the routed url should be for the link, when in reality that's what Razor is going to be doing for YOU. So for the example of mywebsite/service-option-one, the only place you should have service-option-one written down is in your routes map. In your views, you should be doing
#Html.ActionLink("The Anchor Text You Want To Display","Option1","Home")
Then when Razor renders the view, it will translate to
The Anchor Text You Want To Display
http://msdn.microsoft.com/en-us/library/dd505070(v=vs.118).aspx

Related

Why we use routing in asp.net mvc

why use custom routing in asp.net MVC
for example
RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Enable Routing
routes.MapMvcAttributeRoutes();
//custom route for about page
//routes.MapRoute(
// name:"about",
// url: "Home/About",
// defaults: new { controller = "Home",action= "About", id=UrlParameter.Optional}
// );
//custom route for contactus page
//routes.MapRoute(
// name: "about",
// url: "Home/ContactUs",
// defaults: new { controller = "Home", action = "ContactUs", id = UrlParameter.Optional }
// );
//default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
HomeController.cs
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
//[Route("Home/About")]
public ActionResult About()
{
return View();
}
//[Route("Home/ContactUs")]
public ActionResult ContactUs()
{
return View();
}
}
Index.cshtml
IndexPage
About.cshtml
AboutPage
Contactus.cshtml
ContactusPage
when I run the project then write the URL manually then also give output then why use the routing attribute
home/index
home/about
home/contactus
I comment the route attribute and custom route code and above URL give the proper output then why use route attribute
my question is without route attribute easily run the action method then why need to use route attribute above the controller
If you are happy with the default routes, then you don't need to use the route attributes, or put any custom routes in the RouteConfig.
You can add routes to customise how users get to your pages, either through parameters for more dynamic pages, or to make page urls more friendly - for example:
//make about us page url "/about"
routes.MapRoute(
name:"about",
url: "about",
defaults: new { controller = "Home",action= "About"}
);
//make a product page expect an id param in the url
//for example "/catalog/product/pid1"
//"/catalog/product/pid2"
//"/catalog/product/pid3"
//"/catalog/product/pid4" all match this route
routes.MapRoute(
name:"product",
url: "catalog/product/{productId}",
defaults: new { controller = "Catalog",action= "Product"}
);
The same can be achieved in route attributes:
[Route("about")]
public ActionResult AboutUs()
{
return View();
}
[Route("catalog/product/{productId}")]
public ActionResult GetProduct(string productId)
{
//Get product, build view data etc...
return View();
}

How to get the add the query string to actionLink?

The below link gives be the following url: http://localhost:11111/files/Details/3
#Html.ActionLink("Details", "Details", "mycontroller", new { id = item.id },null)
But I'm trying to have a url parameter like this http://localhost:11111/files/Details?id=3 or http://localhost:11111/files/Details.aspx?id=3
How do I get the actionlink to show the url like details?i=3
Here is my controller View:
public ActionResult Details(int? id)
{
...
return View();
}
Why would you like to see the parameter's name in the link?
Asp.Net MVC uses user-friendly URLs.
If you have created a project in Visual Studio using the MVC template, probally your routes, by default, are configured to interpret the parameter after the controller/action/ like the id.
So the id parameter's value in your action will be automatically replaced, by model binding, with the id number present in you URL.
The routing codes can be found under the RegisterRoutes method in the Global.asax file of our project.
I see a cookie already in the RegisterRoutes method.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults);
Using the MapRoute method above, we defined a new route.
Sample ;
public class HaberController : Controller
{
public ActionResult Listele()
{
// Listing codes will be written
return View("Listele");
}
public ActionResult Detay(string HaberId)
{
// Detail codes will be written
return View("Detay");
}
}
We go to our Global.asax file and edit it as follows.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"HaberListeleme",
"Haber",
new { controller = "Haber", action = "Listele" }
);
routes.MapRoute(
"HaberDetay",
"Haber/{id}",
new { controller = "Haber", action = "Detay" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
If we do the routing as follows:
routes.MapRoute(
"HaberDetay",
"Haber/{*Id}",
new { controller = "Haber", action = "Detay" }
);
So if we write * by putting the character next to our parameter name, it will be sent to the related parameter of the Detail method in the Controller, no matter what it says after the News / url tab.
For example:
http://www.doguhanaydeniz.com/Haber/Turkiye/Guncel/34389
If a URL is requested as Turkey / current / 34389 will be sent as a parameter.

Asp.Net MVC 4 routing and link generation

In ASP.NET MVC 4 I wonder about the behavior, how links are generated for me.
Imagine a simple controller with 3 actions, each taking an integer parameter "requestId", for example:
public class HomeController : Controller
{
public ActionResult Index(int requestId)
{
return View();
}
public ActionResult About(int requestId)
{
return View();
}
public ActionResult Contact(int requestId)
{
return View();
}
}
and this registered route (before the default route):
routes.MapRoute(
name: "Testroute",
url: "home/{action}/{requestId}",
defaults: new { controller = "Home", action = "Index" }
);
I call my index-view using http://localhost:123/home/index/8
On this view, I render links for the other two actions:
#Html.ActionLink("LinkText1", "About")
#Html.ActionLink("LinkText2", "Contact")
Now I expect MVC to render this links including the current route-value for "requestId", like this:
http://localhost:123/home/about/8
http://localhost:123/home/contact/8
But i get these links (without the paramter):
http://localhost:123/home/about
http://localhost:123/home/contact
...but not for the index-action if i would specify one:
#Html.ActionLink("LinkText3", "Index")
What I want to avoid is to explicitly specify the parameters in this manner:
#Html.ActionLink("LinkText1", "Contact", new { requestId = ViewContext.RouteData.Values["requestId"] })
When I move the requestId parameter before the action paramter it works like I expect it, but I don't want to move it:
routes.MapRoute(
name: "Testroute",
url: "home/{requestId}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
Can someone explain me this behavior? How can I get this to work without specifying the parameter explicitly?
InController:
Replace the int to nullable int
For Routing:
set requestId as optional in routing
routes.MapRoute(
name: "Testroute",
url: "home/{action}/{requestId}",
defaults: new { controller = "Home", action = "Index" ,requestId=RouteParameter.Optional }
);

URl rewriting in mvc

Hy
i had write below code
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Home", // Route name
"", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute(
"Controller_Action", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { id = UrlParameter.Optional } // Parameter defaults
);
foreach (var route in GetDefaultRoutes())
{
routes.Add(route);
}
routes.MapRoute(
"UserPage", // Route name
"{id}", // URL with parameters
new { controller = "Home", action = "Get" } // Parameter defaults
);
}
private static IEnumerable<Route> GetDefaultRoutes()
{
//My controllers assembly (can be get also by name)
Assembly assembly = typeof(test1.Controllers.HomeController).Assembly;
// get all the controllers that are public and not abstract
var types = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Controller)) && t.IsPublic && !t.IsAbstract);
// run for each controller type
foreach (var type in types)
{
//Get the controller name - each controller should end with the word Controller
string controller = type.Name.Substring(0, type.Name.IndexOf("Controller"));
// create the default
RouteValueDictionary routeDictionary = new RouteValueDictionary
{
{"controller", controller}, // the controller name
{"action", "index"} // the default method
};
yield return new Route(controller, routeDictionary, new MvcRouteHandler());
}
}
i am new to mvc,i want to rewrite my url somthing like this,suppose my url is like www.myhouse.com/product/index/1 then i want to display only www.myhouse.com/prduct-name for better seo performance,i am using mvc4 beta,i had also one through URL Rewriting in .Net MVC but it is not working for me....
but i don't know how to pass pass value to this method.
After lots of searching on the internet, i got my solution
add below code to global.asax
routes.MapRoute(
"Home", // Route name
"", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute(
"jats", // Route name
"{jats}", // URL with parameters
new { controller = "Home", action = "Content" } // Parameter defaults
);
then add below code to view:
#Html.ActionLink("test", "Content", new { jats= "test-test" })
add below code to HomeController:
public ActionResult Content(string jats)
{
return View();
}
then you done...now URL is same as you pass in query string...so your controller name and query string parameter will not display.

Setting up Index as the default route for a controller

I have a url
http://www.roadkillwiki.org/Page/Index/documentation
which I want to turn into
http://www.roadkillwiki.org/Page/documentation
That could also be something like http://www.roadkillwiki.org/Page/my-url-with-spaces - the parameter is a string. The route setup I've tried is:
routes.MapRoute(
"ControllerDefault",
"{controller}/{id}",
new { controller = "Page", action = "Index", id = UrlParameter.Optional }
);
However this is interfering with the default "id" route that MVC projects come with. Is there any way of achieving this?
You don't need to lose the default route. The key to avoiding your routes interfere with each other is to order them so the more specific rules precede the less specific ones. For example:
// Your specialized route
routes.MapRoute(
"Page",
"Page/{slug}",
new { controller = "Page", action = "Index" }
);
// Default MVC route (fallback)
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Then your PageController would look like this:
using System.Web.Mvc;
public class PageController : Controller
{
public string Index(string slug)
{
// find page by slug
}
}
That said, I would strongly advice you to do this instead:
// Your specialized route
routes.MapRoute(
"Page",
"Page/{id}/{slug}",
new { controller = "Page", action = "Index", slug = UrlParameter.Optional }
);
// MVC's default route (fallback)
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
And your PageController:
using System.Web.Mvc;
public class PageController : Controller
{
public string Index(int id)
{
// find page by ID
}
}
By including the page ID either at the beginning of your URL (like StackOverflow does) or at the end, you can then just ignore the slug, and instead retrieve your pages by ID. This will save you a ton of headaches if your users change the page name. I have gone through this and it's painful; you basically have to keep a record of all names your pages have had in the past, just so your visitors/search engines don't get a 404 every time a page is renamed.
Hope this helps.
If you don't need a default route that came with project template you can set up one like this:
routes.MapRoute(
"ControllerDefault",
"{controller}/{pagename}",
new { controller = "Page", action = "Index" }
);
And than in your controller you would have an action:
public ActionResult Index(string pagename)
{
//do something
}

Resources