How to set up specific routing in mvc3 web application - c#

I have problem with routing. I have many pages on my site generated dynamically from database.
First thing which I want to accomplish is to route to these pages like that:
"How to repair a car"
www.EXAMPLE.com/How-to-repair-a-car
For now it works like that: www.EXAMPLE.com/Home/Index/How-to-repair-a-car
Secondly my default page have to be like that: www.EXAMPLE.com
On the Start Page will be news with pagging, so if someone click for instance in the "page 2" button, the address should looks: www.EXAMPLE.com/page =2
CONCLUSION:
default page -> www.EXAMPLE.com (with page = 0)
default page with specific page of news -> www.EXAMPLE.com/page=12
article page -> www.EXAMPLE.com/How-to-repair-car (without parameter 'page') routing sholud point to article or error404
PS: sorry for my english

Try to create route for articles in routing config, like this:
Routing config:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(null, "{article}",
new {controller = "Home", action = "Article" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
HomeController:
public class HomeController : Controller
{
public ActionResult Index(int? page)
{
var definedPage = page ?? 0;
ViewBag.page = "your page is " + definedPage;
return View();
}
public ActionResult Article(string article)
{
ViewBag.article = article;
return View();
}
}
/?page=10 - works
/How-to-repair-car - works
That approach excellent works.

Here is a basic routing example for www.example.com/How-to-repair-car
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace Tipser.Web
{
public class MyMvcApplication : HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"ArticleRoute",
"{articleName}",
new { Controller = "Home", Action = "Index", articleName = UrlParameter.Optional },
new { userFriendlyURL = new ArticleConstraint() }
);
}
public class ArticleConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var articleName = values["articleName"] as string;
//determine if there is a valid article
if (there_is_there_any_article_matching(articleName))
return true;
return false;
}
}
}
}

Related

Special MVC Routing not working

I'm having problems with the routings in my MVC project not working...
I want all my views in the Views > Shared folder like this:
Error.cshtml (default)
Index.cshtml (default)
Overview.cshtml (custom that I made)
Recordings.cshtml (custom that I made)
I've then created one shared controller to handle all views like this:
public class SharedController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Error()
{
return View();
}
public ActionResult Overview()
{
return View();
}
public ActionResult Recordings()
{
return View();
}
}
My RouteConfig.cs looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Map to specific pages under Shared controller:
routes.MapRoute("SharedPages", "{action}/{id}",
new { controller = "Shared", action = #"Overview|Recordings", id = UrlParameter.Optional });
// Use the default rout for all other pages:
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Shared", action = "Index", id = UrlParameter.Optional }
);
// Show the Error page for anything else (404):
routes.MapRoute("Error", "{*url}",
new { controller = "Shared", action = "Error" }
);
}
I want the routing to work like this:
://(url)/ (root - no action specified) --> Shared/Index.cshtml
://(url)/Index --> Shared/Index.cshtml
://(url)/Overview --> Shared/Overview.cshtml
://(url)/Recordings --> Shared/Recordings.cshtml
://(url)/whatever (or if an error occurs) --> Shared/Error.cshtml
But it's not working as expected. If I go to ://(url)/ (root), I get a HTTP 404 - The resource cannot be found. If I go to for example ://(url)/Overview, it's working fine.
How can I make it work like I want?
The order of how you map route is important and first matched route wins. That means that even if there is no resource there one it matches the route it will use it.
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Use specific rout for all other pages:
routes.MapRoute("WhateverA", "WhateverA/{action}/{id}",
new { controller = "WhateverA", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute("WhateverB", "WhateverB/{action}/{id}",
new { controller = "WhateverB", action = "Index", id = UrlParameter.Optional }
);
// Map to specific pages under Shared controller:
routes.MapRoute("RootPages", "{action}/{id}",
new { controller = "Shared", action = "Index", id = UrlParameter.Optional });
// Show the Error page for anything else (404):
routes.MapRoute("Error", "{*url}",
new { controller = "Shared", action = "Error" }
);
}
The problem with the Default and SharedPages routes is that they conflict with each other. You may need to provide specific routes for other controllers if they exist. Other wise the other option is to use Attribute Routing for the other controllers and convention-based routing for your root routes and error
public static void RegisterRoutes(RouteCollection routes)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Attribute routing
routes.MapMvcAttributeRoutes();
// Map to specific pages under Shared controller:
routes.MapRoute("RootPages", "{action}/{id}",
new { controller = "Shared", action = "Index", id = UrlParameter.Optional });
// Show the Error page for anything else (404):
routes.MapRoute("Error", "{*url}",
new { controller = "Shared", action = "Error" }
);
}
With controllers decorated accordingly
[RoutePrefix("WhatEver")]
public class WhatEverController : Controller {
//GET whatever
[HttpGet]
[Route("")]
public ActionResult Index() { ... }
}

URL Routing with an MVC

I am making a website that displays a bunch of articles. It is built off a MVC I want to be able to search for articles by day and then by an ID number via url.
If the domain name is website.com, I'm trying to figure out how to make routes so that website.com/yyyymmdd hits a specific controller+method and displays all the articles for that day and website.com/yyyymmdd/111 searches that day's articles for article #111.
The issue I'm having is that all the tutorials for routing within an MVC assume I will specify the controller and method in the URL. They show something like:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
}
If anybody could suggest a way to automatically make "website.com/yyyymmdd/111" use a specified controller and method, that'd be amazing. Thanks in advance!
EDIT:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"Today",
"{date}/{id}",
new { controller = "Articles", action = "Index", date = DateTime.Today.ToString("yyyyMMdd"), id = UrlParameter.Optional });
}
I've done this as my route and my method is as follows:
public ActionResult ArticlesByDate(string date, int id)
{
if(id > 1)
{
return View(Contact());
}
else
{
return View(About());
}
}
I hope I am understanding your guys' suggestions, but this is giving me a "Resource can not be found" error when i try to navigate to: "http://localhost:52159/20160908/2"
One way this can be solved by using the date as a parameter to the action.
Your action would look like
public ActionResult Index(string articleDate,string id) ...
The your route definition would be something like
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"Default",
"{controller}/{action}/{articleDate}/{id}",
new { controller = "Home", action = "Index",articleDate=DateTime.Today.ToString("yyyyMMdd"), id = "" });
}
Then you can take it from there
Second route for default mvc routing mechanism.
First route is for articles.Controller and action value is static. You can change date and id values for website.com/20160911/111 , website.com/20160912/112 etc.
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "Articles",
url: "{date}/{id}",
defaults: new { controller = "Articles", action = "Info"});
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
public class ArticleController : Controller {
public ActionResult Info(string date, int id){
return View();
}
}
you cant redirect two view in an action. Use one view and partial views within.
for example
Info.cshtml
#if(id > 1)
{
#Html.Partial("_Contact")
}
else
{
#Html.Partial("_About")
}

Asp.net Mvc Route By Only Slug

I'm using ASP.NET MVC 4 with C#. I'm using areas and it's named like "Admin"
Here is my route config;
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(name: "PageBySlug",
url: "{slug}",
defaults: new {controller = "Home", action = "RenderPage"},
constraints: new {slug = ".+"});
routes.MapRoute(name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional},
namespaces: new[] { "Web.Frontend.Controllers.Controllers" });
}
}
I generated frontend page links like; "products/apple-iphone"
So I want to call them like this.
But the error is: The code can't get the controller / action method.
I used frontend page links like;
#Html.ActionLink(linkItem.Title, "RenderPage", routeValues: new {controller = "Home", slug = linkItem.PageSlug})
#Html.RouteLink(linkItem.Title, routeName: "PageBySlug", routeValues: new { controller = "Home", action = "RenderPage", slug = linkItem.PageSlug })
#linkItem.Title
#linkItem.Title
They are rendering url links like; http://localhost:1231/products/apple-iphone
It's like what I want. But when I click any link, asp.net mvc gives me this error:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /products/apple-iphone
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1069.1
Here is my controller;
namespace Web.Frontend.Controllers
{
public class HomeController : BaseFrontendController
{
public ActionResult Index()
{
return View();
}
public ActionResult RenderPage(string slug)
{
return View();
}
}
}
So how can I catch every link request like this combined slug and turn my coded view ?
The problem is, When you request products/iphone, the routing engine don't know whether you meant the slug "products/iphone" or the controller "products" and action method "iphone".
You can write a custom route constraint to take care of this. This constraint will check whether the slug part of the urls is a valid controller or not, if yes,the controller action will be executed.
public class SlugConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection)
{
var asm = Assembly.GetExecutingAssembly();
//Get all the controller names
var controllerTypes = (from t in asm.GetExportedTypes()
where typeof(IController).IsAssignableFrom(t)
select t.Name.Replace("Controller", ""));
var slug = values["slug"];
if (slug != null)
{
if (controllerTypes.Any(x => x.Equals(slug.ToString(),
StringComparison.OrdinalIgnoreCase)))
{
return false;
}
else
{
var c = slug.ToString().Split('/');
if (c.Any())
{
var firstPart = c[0];
if (controllerTypes.Any(x => x.Equals(firstPart,
StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
}
return true;
}
return false;
}
}
Now use this route constraint when you register your custom route definition for the slug. make sure you use {*slug} in the route pattern. The * indicates it is anything(Ex : "a/b/c")(Variable number of url segments- more like a catch all)
routes.MapRoute(name: "PageBySlug",
url: "{*slug}",
defaults: new { controller = "Home", action = "RenderPage" },
constraints: new { slug = new SlugConstraint() }
, namespaces: new string[] { "Web.Frontend.Controllers.Controllers" });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
, new string[] { "Web.Frontend.Controllers.Controllers" });
you can provide only this type of link
#linkItem.Title
Because Routetable find your route using Route name provided by you. so controller name and action name is not necessary.

HTTP 404 Server Error in '/' Application. in ASP.NET MVC 4

`First, this is my first MVC code & I tried to search for the solution to the problem in this site & I checked all the possible cases like routeconfig file, controller,action properties & I tried to put appropriate values in specified page of Web Tab of Project Property. But still it showing the same error. Some help please.
here my routeconfig file
namespace Deepak_MVC_2
{
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 = "Student", action = "GetStudents", id = UrlParameter.Optional }
);
}
}
}
specific page entry : Student/GetStudents
namespace Deepak_MVC_2.Controllers
{
public class StudentController : Controller
{
public ActionResult GetAllStudent()
{
StudentModelManager smm = new StudentModelManager();
List<StudentModel> lsm = smm.GetAllStudentInfo();
ActionResult ar = View("GetStudents",lsm);
return ar;
}
}
}
Update your controller's action to match the View you want. with that You can actually remove the name when returning the view as convention will match the ViewName to the action name.
namespace Deepak_MVC_2.Controllers
{
public class StudentController : Controller
{
public ActionResult GetStudents()
{
StudentModelManager smm = new StudentModelManager();
List<StudentModel> lsm = smm.GetAllStudentInfo();
ActionResult ar = View(lsm);
return ar;
}
}
}
this will allow
GET /Student/GetStudents
to be matched to the correct view as in your image

Handle Multiple action with same name in MVC

In my project there is an action
public ActionResult Lead(int leadId)
{
return View();
}
and in the View an ActionLink was created like this
#Html.ActionLink("Old Link", "Lead", "Home", new { leadId = 7 }, null)
But after some time, to make clean URL, I have changed the name of parameter of that action
public ActionResult Lead(int id)
{
return View();
}
And ActionLink change accordingly
#Html.ActionLink("New Link", "Lead", "Home", new { id = 5 }, null)
But old link was shared in multiple social network sites. Whenever anyone clicks on that old link, he is redirect to the page www.xyx.com/Home/Lead?leadId=7
But now in my application, no such URL exists.
To handle this problem, I was thinking of overloading, but MVC action doesn't support overloading.
I have created another Action with same name with extra parameter, and redirect to new action, but it doesn't work.
public ActionResult Lead(int leadId, int extra=0)
{
return RedirectToAction("Lead", "Home", new { id = leadId });
}
I have found one link to handle such situation, but It is not working in my case.
ASP.NET MVC ambiguous action methods
One possibility to handle this would be to write a custom route:
public class MyRoute : Route
{
public MyRoute() : base(
"Home/Lead/{id}",
new RouteValueDictionary(new
{
controller = "Home",
action = "Lead",
id = UrlParameter.Optional,
}),
new MvcRouteHandler()
)
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var rd = base.GetRouteData(httpContext);
if (rd == null)
{
return null;
}
var leadId = httpContext.Request.QueryString["leadid"];
if (!string.IsNullOrEmpty(leadId))
{
rd.Values["id"] = leadId;
}
return rd;
}
}
that you will register before the default one:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new MyRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
and now you could only have a single action:
public ActionResult Lead(int id)
{
return View();
}
Now both the following urls will work as expected:
www.xyx.com/Home/Lead/7
www.xyx.com/Home/Lead?leadId=7

Categories

Resources