Simple route for mvc not working - c#

I have a very simple normal route and I can't seem to get it to work. I'm kind of clueless what I'm missing.
My routing is:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
My Controller is called AccountController and it has this method:
public virtual ApplicationUser EditUser(String userId)
I post this URL and I get a userid that is null
/Account/EditUser/Patrick
What am I missing?

Your route has a parameter called "id", whereas your method has a parameter called "userId". These need to match.
So either create a route, like:
routes.MapRoute(
name: "EditUser",
url: "Account/EditUser/{userId}",
defaults: new { controller = "Account", action = "EditUser"});
Or change your method to be:
public virtual ApplicationUser EditUser(string id);
Note that if you choose the first option, you need to put that call before the existing default one, because any URL you enter will match against the first route which matches it.

Related

ASP.NET MVC routing task

I have the following route table:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "UserRoute",
url: "{username}",
defaults: new { controller = "User", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
so, when we have url like : http://mysite/abcde it calls UserController, action Index, if we have url like : http://mysite/dashboard/Index it calls DashboardController, action Index. Ok. But when I try to call the following:
return RedirectToAction("Index", "Dashboard");
It calls UserController, action Index with username parameter equals "Dashboard". Why and how to solve?
Your routing is correct (at least for the URLs you provided). But you are not calling the redirect correctly.
When you generate an outgoing route, it doesn't match a URL, it matches the route values that are passed. Your UserRoute contains 3 route values:
username
Controller
Action
So, in order to generate a URL (or redirect) based on this route, you need to pass all 3 parameters.
return RedirectToAction("Index", "Dashboard", new { username = "Fred" });
That said, MVC will automatically reuse route values if they are in the current request. So, if your route already has a username value (for example, you are already at the URL /Fred), it will be able to match the route without specifying the route value explicitly.
return RedirectToAction("Index", "Dashboard");

C# MVC Routing and Ajax Calls

I have the following controller:
public class MyController : BaseController
{
public ActionResult Index(string id) { /* Code */ }
public ActionResult MyAjaxCall(string someParameter) { /* Code */ }
}
I have also added the following in the RouteConfig.cs
routes.MapRoute(
name: "MyController",
url: "MyController/{id}",
defaults: new { controller = "MyController", action = "Index" }
)
So my idea is to be able to go directly to the index action using this url /MyController/{Id}, and that seems to work.
However when on the Index page I need to make an Ajax call to /MyController/MyAjaxCall/{someParameter}. However this url is pointing to the Index controller, and is interpreting MyAjaxCall as the id in the Index action.
Any ideas how I can exclude this action from following the newly added route config setting?
If that your id can only be integer number, you can add a constraint to your id field, which specifies that your id can only be numbers:
routes.MapRoute(
name: "MyController",
url: "MyController/{id}",
defaults: new { controller = "MyController", action = "Index" },
constraints: new { id = #"\d+" } // <- constraints of your parameters
)
Here you can use any regular expression that works for your business logic.
Also make sure to register this route before your default route registration, in that case MVC will first try to match this route, and only if it doesn't match it will try to match the default route.
It sounds like you have the routes in the wrong order. When using MVC routing, the first match always wins, so you must place the most specific routes first before general routes.
routes.MapRoute(
name: "MyControllerAJAX",
url: "MyController/MyAjaxCall/{someParameter}",
defaults: new { controller = "MyController", action = "MyAjaxCall" }
)
routes.MapRoute(
name: "MyController",
url: "MyController/{id}",
defaults: new { controller = "MyController", action = "Index" }
)
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

How to remove question marks in Asp.net MVC routes multiple parameters

When I pass multiple parameters to a controller action, I get question marks in the parameters like this:
http://localhost:57728/Home/AddAndManageProperties?BaseCategoryId=11&SubCategoryId=14
I want to remove the question marks to be like this:
http://localhost:57728/Home/AddAndManageProperties/BaseCategoryId=11/SubCategoryId=14
here is my code:
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 = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "MyRout",
url: "{controller}/{action}/{BaseCategoryId}/{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties", BaseCategoryId = UrlParameter.Optional, SubCategoryId = UrlParameter.Optional }
);
}
}
And here is the Action Method:
public ActionResult AddAndManageProperties(int? BaseCategoryId, int? SubCategoryId)
{
}
And i call the method AddAndManageProperties by this method
[HttpPost]
public ActionResult AddSubCategory(SubCategory subCategory)
{
return RedirectToAction("AddAndManageProperties", new { BaseCategoryId = subCategory.BaseCategoryId, SubCategoryId = subCategory.SubCategoryId });
}
I am new to ASP.NET MVC so please help me!
Move the MyRout to be before the Default route and change it to
routes.MapRoute(
name: "MyRout",
url: "Home/AddAndManageProperties/{BaseCategoryId}/{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
Note that only the last parameter can be marked UrlParameter.Optional so the method needs to be
public ActionResult AddAndManageProperties(int BaseCategoryId, int SubCategoryId)
for the above route, or
public ActionResult AddAndManageProperties(int BaseCategoryId, int? SubCategoryId)
if you modify the above route definition to
defaults: new { controller = "Home", action = "AddAndManageProperties", SubCategoryId = UrlParameter.Optional }
Note, if you also want to include the text "BaseCategoryId" and "SubCategoryId" in the route, use
url: "Home/AddAndManageProperties/BaseCategoryId/{BaseCategoryId}/SubCategoryId/{SubCategoryId}",
That question marks are used for query strings, and they are required because this is how data is assigned to parameters your actions expect. You should not try to remove them, but you could use the [FromBody] attribute, not to send the parameters in query string.
Firstly, and most importantly, your routes are in the wrong order and you have multiple possible URLs that result in calling the wrong route. See Why map special routes first before common routes in asp.net mvc for an explanation.
Secondly, routes cannot contain more than one UrlParamter.Optional.
Third, the = sign is only valid within a query string, unless it is encoded. But IMO, you should not use unsafe characters in a URL to avoid all of the headaches that come with them. A better alternative in this case would be to replace the = with a -.
Finally, if you want to truly make the parameters optional, one approach is to provide multiple routes that allow the parameters in certain routes but not others.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "BaseCategoryAndSubCategoryId",
url: "{controller}/{action}/BaseCategoryId-{BaseCategoryId}/SubCategoryId-{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "BaseCategoryIdOnly",
url: "{controller}/{action}/BaseCategoryId-{BaseCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "SubCategoryIdOnly",
url: "{controller}/{action}/SubCategoryId-{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
NOTE: Stephen's answer is also a good alternative to this approach if your parameters are required to be passed in the URL. IMO, it makes more sense to use required parameters if your action method requires both of them in order to function.
But by far the simplest option is to simply use the query string. The parameters can naturally be optional and appended in any order if you do it that way, and you don't need anything more than your Default route.

RouteConfig setup to accept an optional parameter

I am having problems setting up the RouteConfig file to accept an optional record ID as part of the URL like in the examples below.
http://localhost/123 (used while debugging locally)
or even
http://www.foobar.com/123
Ideally, I would like to have the record ID (123 as in the examples above) be passed in as a parameter to the Index view of the Home controller. I had thought that the default routeconfig would suffice for this (using the ID as an optional element), but apparently the application is apparently trying to direct the browser to a view called '123' which obviously doesn't exist.
My current RouteConfig.cs looks like this:
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 }
);
}
Any assistance on this would be greatly appreciated.
Your routing says:
{controller}/{action}/{id}
that's your site then your controller, then your action and then an id.
You want just site then id:
routes.MapRoute(
name: "Default",
url: "{id}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);
This would then hit a controller at
public class DefaultController : Controller
{
public ActionResult Index(int id)
{
}
}
"{controller}/{action}/{id}" tells MVC that a route may have a controller name, or it may have a controller name followed by an action name, or it may have those two followed by an ID. There's no way, given just an ID, for the routing to understand that it's supposed to be an ID and not an action or a controller name.
If you're never planning to have any other controllers or actions, something like this might work:
routes.MapRoute(
name: "Default",
url: "{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
But that's probably a bad idea. Pretty much every site has at least one key word to indicate what the ID represents. For example, StackOverflow has "/questions/{id}".

asp.net-mvc routing issue : parameters dictionary contains a null entry for parameter

I am trying to set up custom routing with the following mapped route
edit: my full route config
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
#region FixtureAdmin
routes.MapRoute(
name: "FixtureEdit",
url: "{controller}/{action}/{id}",
defaults: new { controller = "FixtureAdmin", action = "Edit", id = UrlParameter.Optional }
);
#endregion
#region Results
routes.MapRoute(
name: "ResultAdd",
url: "{controller}/{action}/{fixtureId}",
defaults: new { controller = "Result", action = "Add", fixtureId = UrlParameter.Optional }
);
#endregion
And my controller code
public ActionResult Add(int fixtureId)
{
// return model to view etc..
}
This is coming up with the exception, even though I have specified the parameter as optional.
The parameters dictionary contains a null entry for parameter 'fixtureId'
The strange thing is, if I change the parameter of the Add action to just 'Id' then the following URL will work Result/Add/1. I'm confused, is there some default routing that is overriding my custom one? Why would changing the parameter to just 'Id' work?
Edit
Just to test, I added another parameter to the action
public ActionResult Add(int? fixtureId, int? testId)
I then edited the route accordingly and now it works, so I reckon it is an issue with default routing.
Use a nullable int in your Controller Action.
public ActionResult Add(int? fixtureId)
{
// return model to view etc..
}
But the question is, if that is indeed an ID, how would it react if a null/blank ID is requested by the user? Is that ID a key in your DB? You can make it nullable if you are able to handle or provide a default page if the ID is blank/null.
EDIT:
This is because ASP.NET will assume that an unidentified parameter in your request is the id, in your case, Results/Add/1, 1 is unidentified. If you want to make that code work with using fixtureId, you should use Results/Add?fixureId=1. So ultimately, it's not because of the routing, but instead, it's because of the parameter in the Action that you have.
EDIT2:
Also, what you are experiencing there is called a routing conflict. Your routes are conflicting with the Default. You can try to apply constraints.
2,
from your post i think your problem is putting your custom route after default, like this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
name: "ResultAdd",
url: "{controller}/{action}/{fixtureId}",
defaults: new { controller = "Home", action = "Add", fixtureId = UrlParameter.Optional }
so:
1/ exception "The parameters dictionary contains a null entry for parameter 'fixtureId'" will come if you dont give the specific route name for any action link or route form because MVC will use default route to routing. So you need to give specific route name to your custom route can be worked, like this:
#Html.ActionLink("Test custom Route", "Add", "Home", new { fixtureId = 1 }, "ResultAdd")
Cheer
Look at this method of adding what the developer calls a 'NullableConstraint' clicky link So if the optional parameter is supplied you can do some checking on it's value.
And also look at the answer following the accepted answer for what seems a simpler, cleaner solution.

Categories

Resources