ASP.NET MVC 4 Incorrect Home Route - asp.net-mvc

after I had added the Product route in my RouteConfig, my default homepage changed to Product page. How can I setup my home controller as my default homepage again.
routes.MapRoute(
name: "Product",
url: "{controller}/{action}",
defaults: new { controller = "Product", action = "Index" }
);
routes.MapRoute(
name: "Products",
url: "products/{categoryName}/{Id}",
defaults: new { controller = "Products", action = "Index", categoryName = "", Id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{action}",
defaults: new { controller = "Home", action = "Index"}
);

This is my route table. It doesn't use the route I marked on the table by default.
Screenshot of the route table

I think the first and last will act the same way.The program will pick the first route it matches so you should hard code the first route like this.
routes.MapRoute(
name: "Product",
url: "Product/{action}",
defaults: new { controller = "Product", action = "Index" }
);
or you should remove the first route. i think that you should go with this approach.
routes.MapRoute(
name: "Products",
url: "products/{categoryName}/{Id}",
defaults: new { controller = "Products", action = "Index", categoryName = "", Id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Explanation:
from a stephen walter's post
The default route table contains a single route (named Default). The Default route maps the first segment of a URL to a controller name, the second segment of a URL to a controller action, and the third segment to a parameter named id.
Imagine that you enter the following URL into your web browser's address bar:
/Home/Index/3
The Default route maps this URL to the following parameters:
controller = Home
action = Index
id = 3
When you request the URL /Home/Index/3, the following code is executed:
HomeController.Index(3)
The Default route includes defaults for all three parameters. If you don't supply a controller, then the controller parameter defaults to the value Home. If you don't supply an action, the action parameter defaults to the value Index. Finally, if you don't supply an id, the id parameter defaults to an empty string.
Let's look at a few examples of how the Default route maps URLs to controller actions. Imagine that you enter the following URL into your browser address bar:
/Home
Because of the Default route parameter defaults, entering this URL will cause the Index() method of the HomeController class in Listing 2 to be called.
Listing 2 - HomeController.cs
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(string id)
{
return View();
}
}
}
In Listing 2, the HomeController class includes a method named Index() that accepts a single parameter named Id. The URL /Home causes the Index() method to be called with an empty string as the value of the Id parameter.
Because of the way that the MVC framework invokes controller actions, the URL /Home also matches the Index() method of the HomeController class in Listing 3.
Listing 3 - HomeController.cs (Index action with no parameter)
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
}
The Index() method in Listing 3 does not accept any parameters. The URL /Home will cause this Index() method to be called. The URL /Home/Index/3 also invokes this method (the Id is ignored).
The URL /Home also matches the Index() method of the HomeController class in Listing 4.
Listing 4 - HomeController.cs (Index action with nullable parameter)
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(int? id)
{
return View();
}
}
}
In Listing 4, the Index() method has one Integer parameter. Because the parameter is a nullable parameter (can have the value Null), the Index() can be called without raising an error.
Finally, invoking the Index() method in Listing 5 with the URL /Home causes an exception since the Id parameter is not a nullable parameter. If you attempt to invoke the Index() method then you get the error displayed in Figure 1.
Listing 5 - HomeController.cs (Index action with Id parameter)
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index(int id)
{
return View();
}
}
}

Related

Default Route with parameters

I have created a controller and I don't want my default Action or View to be named Index. I created Action in TopicsController as below
[ActionName("Index")]
public ActionResult Topics()
{
var topic = new Topic();
return View("Topics", topic.GetTopics());
}
and it mached to URL xyz.com/Topics.
I tried to apply same philosophy to another controller, named, ModulesController but now I have got parameter.
[ActionName("Index")]
public ActionResult Modules(string id)
{
var topic = new Topic();
return View("Modules", topic.GetTopics());
}
but now it is saying
The resource cannot be found.
what I can do so that this action matches URL like xyz.com/Modules/aaaa?
To access the Url xyz.com/Modules/aaaa change the Action name for the Modules action to aaaa like this:
[ActionName("aaaa")]
public ActionResult Modules(string id)
{
var topic = new Topic();
return View("Modules", topic.GetTopics());
}
FYI - It would be better to avoid naming each action with the ActionName filter. At some point it would become difficult to manage. Instead manage the routes in the RouteConfig like this:
routes.MapRoute(
name: "Modules",
url: "{controller}/{action}/{id}",
defaults: new { controller="Modules", action="Modules", id=UrlParameter.Optional }
);
The following Urls will work for the above route:
xyz.com/Modules/aaaa
xyz.com/Modules/aaaa/123
xyz.com/Modules/aaaa?id=123
Update:
If you want 'aaaa' to be the parameter and want to access the action with xyz.com/Modules/aaaa (where 'aaaa' will be bound as the value to the Id variable) then add the following Route to the route table:
routes.MapRoute(
name: "Modules",
url: "Modules/{id}",
defaults: new { controller="Modules", action="Modules", id=UrlParameter.Optional }
);
Note the value of the Url above.

MVC - Passing path to action in controller

Fairly new to MVC, I would like the URLs of my article pages to be like this:-
http://www.example.com/article1
http://www.example.com/article2
http://www.example.com/article3
How can I set up the routing such that whenever someone types in the above it calls an action called article in the controller and passes the path to it?
I tried something like this but to no avail: -
routes.MapRoute(
name: "article",
url: "{article}",
defaults: new { controller = "Home", action = "article" }
);
One solution is to add multiple routes.
routes.MapRoute(
name: "article1",
url: "article1",
defaults: new { controller = "<YourControllerName>", action = "article1" }
);
routes.MapRoute(
name: "article2",
url: "article2",
defaults: new { controller = "<YourControllerName>", action = "article2" }
);
Edit:
From OP's comment, it is understood that there would be 'n' number of articles(urls). To deal with that, we can create a custom route handler.
Step 1: Create a new custom route handler inheriting from MvcRouteHandler
public class CustomRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var controller = requestContext.RouteData.Values["controller"].ToString();
requestContext.RouteData.Values["controller"] = "Home";
requestContext.RouteData.Values["action"] = "Index";
requestContext.RouteData.Values["articleId"] = controller;
return base.GetHttpHandler(requestContext);
}
}
Step 2: Register the new route. Make sure to add this route before default route.
routes.Add("Article", new Route("{controller}", new CustomRouteHandler()));
In the given CustomRouteHandler class, the Controller and Action is hard coded with "Home" and "Index" respectively. You can change that to your own controller and action name. Also you would see a "articleId" setting to RouteData.Values. With that setting, you would get the articleId as a parameter in your Action method.
public ActionResult Index(string articleId)
{
return View();
}
After all the changes, for the url http://www.example.com/article1, the Index() method of HomeController gets invoked with articleId set to 'article1'.
Similarly for http://www.example.com/article2, the Index() method gets invoked with parameter articleId set to 'article2'.

How would I create an MVC route that directs all requests to a single method on a single controller and resolve the route parameter as {id}?

given the following examples
http://my.url/123
or
http://my.url/abc
how would i configure a route that passes either request to the same action method on the same controller
how would I resolve 123 or abc as the input paramter (id) to this action method
public ActionResult Index(String id)
{
ViewData["Message"] = id;
return View();
}
So if I went to http://my.url/123 it would print "123", etc.
thanks in advance!
The following will work, however you may break other routes as you're essentially doing a catch-all on the first part of the path:
routes.MapRoute(
name: "id-route",
url: "{id}",
defaults: new { controller = "YourController", action = "YourAction", id = "{id}"
});

Routing without Action Name in Url

I'm having problems with routing. I have News controller and I can read the details of a news from url http://localhost/News/Details/1/news-title(slug). Here is no problem for now. But I created a controller called Services with Index action. Route config:
routes.MapRoute(
"Services",
"Services/{id}",
new { controller = "Services", action = "Index" }
);
When my Index Action is
public ActionResult Index(string title)
{
return View(title);
}
I write localhost:5454/Services/sometext by hand in browser it works.
But when change my index action to
public ActionResult Index(string title)
{
Service service = _myService.Find(title);
ServiceViewModel = Mapper.Map<Service , ServiceViewModel >(service );
if (service == null)
{
return HttpNotFound();
}
return View(serviceViewModel);
}
I get Http Error 404 Not Found for Url localhost/Services/ITServices.
I can add this services from admin page with it's title (ITServices for example).
Then I do foreach in my Home Page for the services links
#foreach (var service Model.Services)
{
<div class="btn btn-success btn-sm btn-block">
#Html.ActionLink(service.Title, "Index", new { controller = "Services", id = service.Title })
</div>
}
But I can't show the page in localhost/Services/ITServices.
When I click on the link I want to go to page localhost/Services/ITServices and it has to show the content(which can be added from admin page) like in the news. But I don't want to use it with action name and ids like in the news. How can I achieve this?
EDIT
Ok. I add FindByTitle(string title) in repository. I changed the id to title in RouteConfig and in the link in Home Page View. Then in my domain model deleted Id and updated Title as [Key]. Now it works. Only have to check with remote validation for possible duplicates of Title when adding new from admin page.
The parameter name in the URL template does not match the argument on the Action (Index).
So you can do one of two things.
Change the template parameter to match the argument of the Action
routes.MapRoute(
name: "Services",
url: "Services/{title}",
defaults: new { controller = "Services", action = "Index" }
);
Where Action Index is
public ActionResult Index(string title) { ... }
or you change the argument of the Action Index to match the paramater in the url template
public ActionResult Index(string id) { ... }
Where the route mapping is
routes.MapRoute(
name: "Services",
url: "Services/{id}",
defaults: new { controller = "Services", action = "Index" }
);
But either way the route is not finding route because it cannot match the parameters.
In fact if the intention is to use the title as a slug you could go so far as to use a catch all route for services like
routes.MapRoute(
name: "Services",
url: "Services/{*title}",
defaults: new { controller = "Services", action = "Index" }
);
Take a look at the answers provided here
how to route using slugs?
Dynamic routing action name in ASP.NET MVC
Try this:
public ActionResult Index(string id)

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 }
);

Resources