MVC Controller Action Parameter is null - asp.net-mvc

I have Controller name: District and Action name: Incharges But I want the URL to be like this (action name with some paremeter)
www.example.com/district/incharges/aaa
www.example.com/district/incharges/bbb
www.example.com/district/incharges/ccc
But, while debugging teamName always return as NULL in the action parameter.
Routing
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"DistrictDetails",
"District/Incharges/{teamName}",
new { controller = "District", action = "Incharges" }
);
Controller
But, while debugging teamName always return as NULL in the action parameter.
public class DistrictController : Controller
{
public ActionResult Incharges(string teamName)
{
InchargePresentationVM INPVM = new InchargePresentationVM();
INPVM.InitializePath(teamName, string.Empty);
return View("", INPVM);
}
}
View
#{
ViewBag.Title = "Index";
}
<h2>Index About</h2>

specific route you have to declare the first
routes.MapRoute(
"DistrictDetails",
"District/Incharges/{teamName}",
new { controller = "District", action = "Incharges", id = UrlParameter.Optional }
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
););

ASP.NET MVC DefaultModelBinder will try and do implicit type conversion of the values from your value provider , eg. form, to the action method parameters. If it tries to convert a type from the value provider to the parameter and it is not able to do it, it will assign null to the parameter.
Regarding routing, ASP.NET MVC has the concept of conversion over configuration. If you follow the conversion, then instead of configuration. You can keep your default route and always have the route you want by naming your controllers, action methods and parameter names.
With the convention over configuration you must keep the default HomeController which is the entry point of the application and then name other controllers as below. These can conform to the route names you want.
namespace ConversionOverConfiguration
{
public class DistrictController: Controller
{
public ActionResult Incharges(int aaa)
{
//You implementation here
return View();
}
}
}
The route will look as below if you have this conversion implementation
//Controller/ActionMethod/ActionMethodParameter
//District/Incharges/aaa
And this will give you domain URI:www.example.com/district/incharges/aaa . If action method parameter type is a string, then domain URI is:www.example.com/district/incharges/?aaa=name
is a string. Then you can keep the ASP.NET MVC default routing
routes.MapRoute
(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional
});

Related

MVC url routing with slug and id. Makes a mess with default routing

Im trying to get my urls to look nice and seo friendly with slugs. I tought I suceeded but then my default routing stopped working.
When I go to this example.com/location/viewlocation/528 then the url ends up like example.com/528/a-nice-location
So thats good!
But now my normal stuff dosent work.
Typing in example.com/home/index results in the error
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult ViewLocation(Int32, System.String)' in 'Oplev.Controllers.LocationController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
I have tried different solutions but I a missing something. Cant get it to work.
My code:
RouteConfig
routes.MapRoute(
name: "view_location",
url: "{id}/{slug}",
defaults: new { controller = "Location", action = "ViewLocation", id = UrlParameter.Optional, slug = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Location controller
public ActionResult ViewLocation(int id, string slug)
{
if (string.IsNullOrEmpty(slug))
{
slug = "a-nice-location"; // testing..
return RedirectToRoute("view_location", new { id = id, slug = slug });
}
return View();
}
Home controller
public ActionResult Index()
{
return View();
}
Your first route matches anything with 0, 1 or 2 segments in the url. For example it matches ../Home/Index. You need some way to distinguish it, for example you could make it
routes.MapRoute(
name: "view_location",
url: "ViewLocation/{id}/{slug}",
defaults: new { controller = "Location", action = "ViewLocation", slug = UrlParameter.Optional }
);
or you could add a route constraint
Note also that only the last parameter can be marked as UrlParameter.Optional, but in your case the id is not optional anyway
Ok so I somehow ended up with something that works!
Changed routing for view_location to this:
routes.MapRoute(
name: "view_location",
url: "{id}/{slug}",
defaults: new { controller = "Location", action = "ViewLocation", slug = UrlParameter.Optional},
constraints: new { id = #"\d+" }
);
This is meant to supplement the already given answers. Attribute routing with route constraints will also work.
First make sure attribute routing is enabled in RouteConfig
//Attribute routing
routes.MapMvcAttributeRoutes(); // placed before convention-based routes
//convention-based routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Next use the necessary Route attributes on the controller
[HttpGet]
[Route("{id:int}/{*slug?}", Name = "view_location")] // Matches GET 528/some-nice-location
public ActionResult ViewLocation(int id, string slug) {
if (string.IsNullOrEmpty(slug)) {
slug = "a-nice-location"; // testing..
return RedirectToRoute("view_location", new { id = id, slug = slug });
}
return View();
}

Change url asp.net mvc 5

routes.MapRoute(
name: "MyRoute",
url: "{Product}/{name}-{id}",
defaults: new { controller = "Home", action = "Product", name = UrlParameter.Optional , id = UrlParameter.Optional }
);
my routemap and i want my url in product action be like = http://localhost:13804/Wares/Product/name-id
but now is like =
http://localhost:13804/Wares/Product/4?name=name
When defining a route pattern the token { and } are used to indicate a parameter of the action method. Since you do not have a parameter called Product in your action method, there is no point in having {Product} in the route template.
Since your want url like yourSiteName/Ware/Product/name-id where name and id are dynamic parameter values, you should add the static part (/Ware/Product/) to the route template.
This should work.
routes.MapRoute(
name: "MyRoute",
url: "Ware/Product/{name}-{id}",
defaults: new { controller = "Ware", action = "Product",
name = UrlParameter.Optional, id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Assuming your Product action method accepts these two params
public class WareController : Controller
{
public ActionResult Product(string name, int id)
{
return Content("received name : " + name +",id:"+ id);
}
}
You can generate the urls with the above pattern using the Html.ActionLink helper now
#Html.ActionLink("test", "Product", "Ware", new { id = 55, name = "some" }, null)
I know its late but you can use built-in Attribute Routing in MVC5. Hope it helps someone else. You don't need to use
routes.MapRoute(
name: "MyRoute",
url: "{Product}/{name}-{id}",
defaults: new { controller = "Home", action = "Product", name = UrlParameter.Optional , id = UrlParameter.Optional }
);
Instead you can use the method below.
First enable attribute routing in RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
}
Then in WaresController
[Route("Wares/Product/{name}/{id}")]
public ActionResult Product(string name,int id)
{
return View();
}
Then to navigate write code like this in View.cshtml file
Navigate
After following above steps your URL will look like
http://localhost:13804/Wares/Product/productname/5

Call function after routeconfig in MVC controller

I have done a route configuration with MVC. The route is so defined:
routes.MapRoute(
name: "Box",
url: "boxes/{id}",
defaults: new { controller = "Boxes", action = "Index", id = UrlParameter.Optional }
);
The problem is that when i call a javascript function from the view Boxes, all the function i call are redirected to the Index function.
For example, if i call var url = "/Boxes/ReturnPrice"; the site don't call this function but the index function.
The index function in boxesController is so defined:
public ActionResult Index()
{
//Code here
return view();
}
When you call /Boxes/ReturnPrice , It matches your "Box" route definition. the framework will map "ReturnPrice" from the url to the id parameter !
You need to define a route constraint which tells that your id property is of type int ( I assume it is int in your case) . Also you need to make sure that you have a generic route definition exists to handle your normal requests with the format controllername/actionmethodname.
You can define the route constraint when defining the route using regex.
routes.MapRoute(
name: "Box",
url: "boxes/{id}",
defaults: new { controller = "Boxes", action = "Index", id = UrlParameter.Optional },
constraints: new { id = #"\d+" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
With this Boxes/ReturnPrice will go to ReturnPrice action method while Boxes/5 will go to Index action method with value 5 set to Id param.

why i have to pass parameter as a querystring to Action Method in MVC?

I'm new to mvc. I'm creating a test application in mvc.
here I've studied that mvc works with url as /[Controller]/[ActionName]/[Parameters]
But in my application i have to pass parameter as /home/index?name=test. I think it should work as /home/index/test. But it doesn't work in this way.
Here is ActionMethod in homeController
public ActionResult Index(String name)
{
ViewBag.name = name;
return View();
}
Routing code in Global.asax.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Index.cshtml
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>#ViewBag.name</h2>
Can anyone help me to findout that why its not working in /home/index/test format.
Thanks.
Routes.MapRoute(
"DefaultWithName", // Route name
"{controller}/{action}/{name}", // URL with parameters
new { controller = "Home", action = "Index", name = UrlParameter.Optional }
Because your optional parameter says "id", and in your controller it's "name".
As Lars points out, your route specifies the default parameter name as ID. Your controller specifies it as "name." If you changed your controller parameter to say, int ID, then home/index/3 would work.
As pointed by #Lars & #Joel, your route specifies the default parameter name as ID.
Declare
routes.MapRoute(
"DefaultWithName", // Route name
"{controller}/{action}/{name}", // URL with parameters
new { controller = "Home", action = "Index", name = UrlParameter.Optional });
And to use route use code
#Url.RouteUrl("DefaultWithName", new { name = "test" })
Instead of #Url.Action

How do I set up RESTFul URLs using ASP.NET MVC routing?

I have this URL:
/controller/action/value
and this action:
public ActionResult Get(string configName,string addParams)
{
}
How do I set up my routing table to get the routing engine bind the value to the configName parameter for any action in the Config controller?
Well, first off, that is incomplete. You don't have a method name.
Secondly, this will already work with URLs of the format:
/controller/action?configName=foo&addparams=bar
Here's how to do it with pretty routes:
routes.MapRoute(
"YourMapping",
"{controller}/{action}/{configName}/{addParams}");
or
routes.MapRoute(
"YourMapping",
"{controller}/{configName}/{addParams}",
new {
controller = "YourController",
action = "YourAction"
},
new {
controller = "YourController" // Constraint
});
if you want to exclude the action from the URL.
You could add a new route above the default
routes.MapRoute(
"Config",
"config/{action}/{configName}/{addParams}",
new { controller = "Config", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Which will allow you to use the route /config/actionName/configName/addParamsValue. Your other routes should be unaffected by this.
routes.MapRoute(
"ValueMapping",
"config/{action}/{configName}/{addParams}",
new { controller = "Config", action = "Index", configName= UrlParameter.Optional, addParams = UrlParameter.Optional } // Parameter defaults);
Setting default Controller to Home, with a Default Action of Index
So the Url:
/config/get/configNameValue/AddParamValue
would match this Method:
public ActionResult Get(string configName,string addParams)
{
//Do Stuff
}

Resources