Error in Routing in ASP.NET MVC - c#

I am trying to search a movie from a list. However, the search string always returns null.
My Controller Code
public ActionResult Index()
{
return View(db.Movies.ToList());
}
public ActionResult Search(string searchstring)
{
var movies = from m in db.Movies
where m.Title.Contains(searchstring)
select m;
return View(movies.ToList());
}
// GET: Movies/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
Routing Configuration
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Movies", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Search",
url: "{controller}/{action}/{searchstring}"
);
I am able to get the list of movies from Index action. The URL I am passing is http://localhost:52872/Movies/Search/GodFather
However if I place my Search route above the Default route, it works fine, but the edit, and details does not work.

Route conflict. First route template matches so it does not reach the second one.
Order of route definition is also important for the same reason.
Refactor to
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Search",
url: "Movies/Search/{searchstring}",
defaults: new { controller = "Movies", action = "Search"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Movies", action = "Index", id = UrlParameter.Optional }
);

Related

Custom URL in mvc .net

I currently have the following url implemented:
https://example.com/controller/challenge/{params}
and would like to create a second url that accepts a different set of parameters: https://example.com/controller/v2/challenge/{params}.
I cannot seem to get the "v2" to be hardcoded into the url path. Rather, the only way I can make it work at the moment is using https://example.com/controller/challengev2/{params}
In my configuration file:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "controller", action = "Challenge", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "ChallengeV2",
url: "{controller}/{action}/{id}",
defaults: new { controller = "controller", action = "Challengev2", id = UrlParameter.Optional }
);
My controller is set up like:
public async Task<ActionResult> Challenge(string resumePath, string refid, string client_id)
{
}
[ActionName("Challengev2)]
public async Task<ActionResult> Challenge(string refid)
{
}
I have tried modifying the url when defining the route to:
routes.MapRoute(
name: "ChallengeV2",
url: "controller/v2/Challenge/{id}",
defaults: new { controller = "controller", action = "Challengev2", id = UrlParameter.Optional }
);
But this seems to throw a 404 error. Is there a step that I am missing to create that endpoint?
Switch the order you define your routes. The order plays an extremely important role.
routes.MapRoute(
name: "ChallengeV2",
url: "controller/v2/Challenge/{id}",
defaults: new { controller = "controller", action = "Challengev2" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "controller", action = "Challenge", id = UrlParameter.Optional }
);
To create a v2 route prefix, I would recommend you to use route attribute instead of route map.
Using route attribute, your code would be like this:
public class ChallengeController
{
[Route("/challenge/{resumePath}/{refid}/{client_id}")]
public async Task<ActionResult> Challenge(string resumePath, string refid, string client_id)
{
// ...
}
[Route("/v2/challenge/{refid}")]
public async Task<ActionResult> Challenge(string refid)
{
// ...
}
}

set index action default action controller in asp.net mvc

I am trying to make index action is the default action in this controller when i write
http//mydomain/action
call index action > http//mydomain/case-studies
will call index action
my problem when i write the url gives me this message The resource cannot be found.
the url i write it http//mydomain/case-studiesit should be call index action but The resource cannot be found.
This is the controller
[RoutePrefix("case-studies")]
public class case_studiesController : Controller
{
// GET: CaseStudies
[Route("Index")]
public ActionResult Index()
{
return View("/views/case-studies/Index.cshtml");
}
[Route("adaep")]
public ActionResult adaep()
{
return View("/views/case-studies/pagename.cshtml");
}
}
this is my route
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 = "Index", id = UrlParameter.Optional }
);
}
}
This answer worked with me to keep home route as default and make default action for every controller i changed this from [Route("Index")] to [Route("")] with the same route
[Route("")]
public ActionResult Index()
{
return View("/views/case-studies/Index.cshtml");
}
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 = "Index", id = UrlParameter.Optional }
);
}
}
That route does that.the definition of the route is: if {controller} is empty use "Home" if {action} is empty use "index" if {id} has value place in the id parameter. for every url that has only the controller name, the request should go the index action
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This is because your MapRoute is incorrect you're MapRoute is having a default controller of Home:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
change it to:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "case-studies", action = "Index", id = UrlParameter.Optional }
);

C# Asp.Net MVC - Parameter Only Action Request [duplicate]

This question already has answers here:
Routing in ASP.NET MVC, showing username in URL
(2 answers)
Closed 4 years ago.
I have an Asp.Net MVC project whereby we allow our users to have public profiles.
I would like to improve the url, so that it is more friendly, and shorter.
The existing code is as follows -
public class ProfileController : Controller
{
private readonly IUserProfileService _userProfileService;
public ProfileController(IUserProfileService userProfileService)
{
this._userProfileService = userProfileService;
}
public ActionResult Index(string id)
{
//Get users profile from the database using the id
var viewModel = _userProfileService.Get(id);
return View(viewModel);
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Required for the route prefix attributes to work!
routes.MapMvcAttributeRoutes();
routes.MapRoute(
"ProfileUrlIndexActionRemoval",
"Profile/{id}",
new { controller = "Profile", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
The aforementioned code allows the following url to work (based on the default MVC routing) - www.mydomain.com/profile/john-doe
What routing do I need to implement, in order to allow the following url to work instead - www.mydomain.com/john-doe
Thanks.
This is a little tricky as you want the friendly URL in the root of the site while not conflicting with any other routes.
That would mean that if you have any other routes like About or Contact you would need to make sure that are in the route table before the friendly route to avoid route conflicts.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Required for the route prefix attributes to work!
routes.MapMvcAttributeRoutes();
routes.MapRoute(
"ProfileUrlIndexActionRemoval",
"Profile/{id}",
new { controller = "Profile", action = "Index" }
);
routes.MapRoute(
name: "Home",
url: "Home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "About",
url: "About/{action}/{id}",
defaults: new { controller = "About", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Contact",
url: "Contact/{action}/{id}",
defaults: new { controller = "Contact", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default_Frieldly",
"{*id}",
new { controller = "Profile", action = "Index" }
);
}
}
And finally because the default route will capture all unmatched routes, you will need to take not found profiles into account.
public class ProfileController : Controller {
//...code removed for brevity
public ActionResult Index(string id) {
//Get users profile from the database using the id
var viewModel = _userProfileService.Get(id);
if(viewModel == null) {
return NotFound();
}
return View(viewModel);
}
}
By having the profile controller prefix in the original URL it made it unique so as to avoid route conflicts, but in wanting the root friendly URL, while not impossible, you see the hoops needed to jump through in order to get the desired behavior.
This is how I would do it. Register a route that matches any string after the root slash.
Note that this severely limits the routes you can use for the application since not everything matching /{id} may actually be a user ID, which is why applications will typically prefix the route with /profile or /p.
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "UserIdRoute",
url: "{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
public ActionResult Index(string id)
{
//Get users profile from the database using the id
var viewModel = _userProfileService.Get(id);
return View();
}

Route URL must be started with '/'

I've declared Index action in Home controller:
[HttpGet]
public ActionResult Index(string type)
{
if (string.IsNullOrEmpty(type))
{
return RedirectToAction("Index", new { type = "promotion" });
}
return View();
}
That accepts:
https://localhost:44300/home/index?type=promotion
and
https://localhost:44300/?type=promotion
Everything was ok until I config route for 404 page:
routes.MapRoute(
name: "homepage",
url: "home/index",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "default",
url: "/",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
"404-PageNotFound",
"{*url}",
new { controller = "Error", action = "PageNotFound" }
);
Invalid syntax:
The route URL cannot start with a '/' or '~' character and it cannot
contain a '?' character.
If I remove the second configuration,
https://localhost:44300/?type=promotion
wouldn't be accepted. -> Show 404 page.
My question is: Is there a way to config route URL start with '/' (none controller, none action)?
Your route is misconfigured, as the error states it cannot begin with a /, and for the home page it doesn't need to. In that case it should be an empty string.
routes.MapRoute(
name: "default",
url: "",
defaults: new { controller = "Home", action = "Index" }
);
However, it is a bit unusual (and not SEO friendly) to want to map more than one route to the home page of the site as you are doing.
It is also unusual to do a redirect to a home page, which does an additional round trip across the network. Usually routing directly to the page you want will suffice without this unnecessary round trip.
routes.MapRoute(
name: "homepage",
url: "home/index",
defaults: new { controller = "Home", action = "Index", type = "promotion" }
);
routes.MapRoute(
name: "default",
url: "/",
defaults: new { controller = "Home", action = "Index", type = "promotion" }
);
// and your action...
[HttpGet]
public ActionResult Index(string type)
{
return View();
}

ASP.NET Routing where two controller actions have the same number of parameters

We have a route config like so:
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "About",
url: "{controller}/{action}/{aboutId}",
defaults: new { controller = "Home", action = "About" }
);
routes.MapRoute(
name: "Contact",
url: "{controller}/{action}/{contactId}",
defaults: new { controller = "Home", action = "Contact" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
You will notice that there are two routes that have one mandatory extra parameter. The routes About and Contact.
In our app we have two urls
www.myapp.com/Home/About/2 which works fine.
But when we navigate our browser to www.myapp.com/Home/Contact/5 we get the dreaded routing exception:
The parameters dictionary contains a null entry for parameter 'contactId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Contact(Int32)' in 'RoutingTest.Controllers.HomeController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
If we change the sequence of the routing so that it looks like so:
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Contact",
url: "{controller}/{action}/{contactId}",
defaults: new { controller = "Home", action = "Contact" }
);
routes.MapRoute(
name: "About",
url: "{controller}/{action}/{aboutId}",
defaults: new { controller = "Home", action = "About" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Then the Contact url works but the About url does not.
The HomeController looks like this:
public class HomeController : Controller {
public ActionResult Index() {
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult About(int aboutId) {
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact(int contactId) {
ViewBag.Message = "Your contact page.";
return View();
}
}
What this seems to imply is that two routings cannot have the same number of parameters regardless of the name of the Controller Action. If the two controller actions have a parameter with the same name, then all works fine. I know I can start doing very hacky things to work around this problem such as calling all parameters the same name or giving the actions meaningless parameters to change the number of parameters but I would actually like to know what is happening under the hood.
How do I solve this problem?
The root (no pun intended) of your issue ISN'T that routes can't have the same number of params. They can. The issue is that the routing engine will select the first route that matches the incoming request. Your routes are only different by the defaults, and pattern matching-wise they are exactly the same. So in each and every case you should be hitting the Contact route.
It looks like you are trying to have different routes based on the action. Which I can't actually see why you NEED.
You CAN use the following for that effect.
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Contact",
url: "Home/Contact/{contactId}"
);
routes.MapRoute(
name: "About",
url: "Home/About/{aboutId}"
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
However. I HIGHLY recommend against this approach, as your "default" route would be the Contact route. This means that (under Razor) the #Html.ActionLink() and related methods will be...wrong.
Honestly, it should just work perfectly if you actually just use...
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Specify controller and/or action in a route explicitly to allow routing to pick correct route:
routes.MapRoute(
name: "About",
url: "{controller}/About/{aboutId}",
defaults: new { controller = "Home", action = "About" }
);
You also can add constraints to parameters to distinguish between routes, but it looks like in your case both actions have the same integer parameter.
Couldn't you just delete your custom routes and just reuse the {id} parameter (turn {contactId} and {aboutId} into just "id" in your action code)?
public class HomeController : Controller {
public ActionResult Index() {
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult About(int id) {
int aboutId = id;
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact(int id) {
int contactId = id;
ViewBag.Message = "Your contact page.";
return View();
}
}

Categories

Resources