Masters,
I've defined few routes as follow.
routes.MapRoute(
name: "Default1",
url: "{a}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default2",
url: "{a}/{b}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default3",
url: "{a}/{b}/{c}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default4",
url: "{a}/{b}/{c}/{d}",
defaults: new { controller = "Home", action = "Index" }
);
and in HomeController,
public ActionResult Index(dynamic data)
{
return View();
}
I set a break-point at begining of Index method
Now, when i hit URL like : http://{MylocalIP:port}/a/b sticks on break point.
but I am unable to extract route values that is a & b.
How can we do this?
Please help.
Thanks in advance
Even if you manage to get this to work you would have to case your controller action to handle the different parameter. Why not just create different actions depending on the number of parameters and avoid such usage altogether. If you are trying to provide properties of a Model that may not always have values then create a Model and instead of passing dynamic pass the Model to the action.
The modelbinder doesn't know what to do with a dynamic action parameter. The closest that I'm aware of is JObject, in JSON.net.
You will still have to figure out what what type you have received, deserialize it, and return the appropriate view.
I had a similar requirement of an action and a dynamic number of parameters. In my case, I needed to include a folder path as part of the URL. This path can include different number of sub-folders. MVC would interpret the sub-folders as parameters. I found a way to solve this in this article by Bipin Joshi.
I wrote my route this way:
routes.MapRoute(
name: "Portfolio",
url: "Portfolio/{*id}",
defaults: new { controller = "Portfolio", action = "Index", id = UrlParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint("GET") }
);
I used a hard coded "Portfolio" because this route only affects that controller. You can make your route dynamic with :
url: "{controller}/{*id}"
I built the controller this way:
public class PortfolioController : Controller
{
public ActionResult Index(string id)
{
//Get Pictures from folder 'id'
}
}
You can check the results here.
Related
I'm writing few routes for my MVC application. I have the following routes for my application:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Pages", action = "Index", id = UrlParameter.Optional }
);
The route above is used when I want to access default values like:
www.servicili.com/budget/edit/1
www.servicili.com/professional/view/234
But, I create the following route for a specific purpose:
routes.MapRoute(
name: "Perfil",
url: "{UsuApelido}",
defaults: new { controller = "Perfil", action = "Index"}
);
the route above, is used to access the URL profile of a "plumber" for example:
www.servicili.com/MarkZuckberg
the profile details are on the controller Perfil and Action Index, however, since I wrote this route, all other actions aren't working.
For example: If I try to access the Index action inside another controller, it redirect to Index of Perfil.
--
The question is: Since I wrote a route for a specific Action of a Controller, do I need to write a route for all Actions inside the Controller?
To solve your problem try like this,
First define constraint,
public class PlumberUrlConstraint: IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var db = new YourDbContext();
if (values[parameterName] != null)
{
var UsuApelido = values[parameterName].ToString();
return db.Plumbers.Any(p => p.Name == UsuApelido);
}
return false;
}
}
Define two routes, put "Default" route at 2nd position
routes.MapRoute(
name: "Perfil",
url: "{*UsuApelido}",
defaults: new { controller = "Perfil", action = "Index"},
constraints: new { UsuApelido = new PlumberUrlConstraint() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Pages", action = "Index", id = UrlParameter.Optional }
);
Now if you have an 'Index' action in 'Perfil' Controller, you can get plumber name like this,
public ActionResult Index(string UsuApelido)
{
//load the content from db with UsuApelido
//display the content with view
}
Hope this help.
I have this Controller:
public class TestController : Controller
{
// GET: Test
public ActionResult Index()
{
return View();
}
public ActionResult Edit(int accessLevel)
{
return View();
}
}
Set up in RouteConfig.cs as:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Test Edit",
url: "Test/Edit/{accessLevel}",
defaults: new { controller = "Test", action = "Edit", accessLevel = UrlParameter.Optional }
);
If I go to this URL:
http://localhost:35689/Test/Edit/2
I get this error:
The parameters dictionary contains a null entry for parameter
'accessLevel' of non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult Edit(Int32)' in
'MyProject.Mvc.Client.Controllers.TestController'. An optional
parameter must be a reference type, a nullable type, or be declared as
an optional parameter. Parameter name: parameters
Any idea why that is? I would think that I'm providing the right datatype with /2.
The specific route definition should be defined before the generic default one.The order of route definitions really matters.
routes.MapRoute(
name: "Test Edit",
url: "Test/Edit/{accessLevel}",
defaults: new { controller = "Test", action = "Edit",
accessLevel = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
If you keep the other order like what you have (Generic-default first ,specific one later), When a request comes for Test/Edit/2 It will be matched to the generic route definition because Test is a valid controller and Edit is a valid action method name and 2 could be a valid param value for Id param.
Since the request got a valid route definition to match to it's url pattern, It will never be evaluated against other route definitions defined below the first one.
Keep all specific route definitions first and have the generic-default one as the very last one.
Or You may use attribute routing to define this route pattern in the Test controller.To enable attribute routing, you can call the MapMvcAttributeRoutes method in the RegisterRoutes method of RouteConfig.cs. You will still keep the default route definition there.
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 }
);
}
and in your TestController
[Route("Test/Edit/{id?}")]
public ActionResult Edit(int? id)
{
//check id value and return something
}
Also, there is no point in defining a custom route if it matches with the generic default route definition. In your case, Even if you do not define the custom route ,Test/Edit/2 will go to the Edit action method of TestController as the request matches the default route definition.
People usually use these custom route definition to create nice url patterns like
[Route("Product/{id}/{name}")]
public ActionResult View(int id,string name)
{
//check id value and return something
}
This route definition will match the request Product/34/seo-friendly-name. Take a look at the URL of this question and you will understand what i am explaining here.
Switch the routes in RoutesConfig.cs. They should go from the most specific to general.
Your Default route is catching this one.
Please interchange your Route in RouteConfig becuase Order of routes are really matters a lot.
I have this method in my Home controller:
public ActionResult RequestExamReview(string EC)
I have this link in my view (in debug mode):
http://localhost:50909/Home/RequestExamReview/201507LH123
But when I debug into the method and check EC, it is null.
What am I doing wrong? I'm using the default routing, do I need to create a new route definition:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
You have a couple options:
You can name the parameter in your method "id" like it is defined in your route
public ActionResult RequestExamReview(string id)
You can specify a new route that has the value ec as a parameter (but I wouldn't recommend this)
If you were to do that it would look something like this:
routes.MapRoute(
name: "Default",
url: "Home/RequestExamReview/{ec}",
defaults: new { controller = "Home", action = "RequestExamReview" }
);
You can use this url instead:
http://localhost:50909/Home/RequestExamReview?EC=201507LH123
You can use the Bind attribute to rename your parameter to id
public ActionResult RequestExamReview([Bind(Prefix="id")] string EC)
I wouldn't recommend adding a new route because it is best to keep the number of routes small to reduce complexity. You will find that as your app grows, managing the number of routes will become painful if you add a new route just to custom name your variables. In your case I would recommend just using the url with the query string values.
In my MVC application, when user goes to www.MyDomain.com/Home, this request is processed in HomeController class Index method due to following routing entry in Global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Let's say if user goes to www.MyDomain.com/SomeParameters, I want this request to be processed in MyController class Index method. An example for the parameters will be www.MyDomain.com/John. For this I have created following entry in Global.asax but it does not seem to get hit. Can anyone point out what I am doing wrong here?
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "MyController", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
The routing handles John as the controller, not the action. So in your example John is the controller and because you don't provide an action, it takes Index as the default action.
If you want www.MyDomain.com/John to be routed to controller MyController, action Index and a parameter that contains John, a solution could be to add the following route (before the default route):
routes.MapRoute(
name: "MyController",
url: "{myparameter}",
defaults: new { Controller = "MyController", Action = "Index" });
And the controller:
public ActionResult Index(string myparameter)
{
return View("whatever");
}
This will lead www.MyDomain.com/John to the Index action with myparameter = "John".
ps. In the example myparameter is mandatory.
In order to have www.MyDomain.com/SomeParameters you simply need to create a route where the Controller and the Action method are defaulted since they will not be provided in the URL.
Make sure the route definition only includes the someparameters and does not have anything else. This way you can just treat anything in the URL after / as a parameter.
routes.MapRoute(
name: "MyController",
url: "{someparameters}",
defaults: new { Controller = "MyController", Action = "Index" });
public ActionResult Index(string someparameters)
{
...
return View();
}
I am working with ASP.NET MVC 4 and am attempting to write a really basic route, but it's not working and getting very frustrated with it!
I want the URL http://www.mywebsite.com/my-page to trigger the controller called Page and the action method Index.
I have no other route setup apart from this:
RouteTable.Routes.MapRoute(
name: "Default",
url: "my-page",
defaults: new { controller = "Page", action = "Index" }
);
Is there something incorrect with my setup or where am I going wrong?
The error I get is:
The controller for path '/my-page' was not found or does not implement IController.
Main problem is you are trying to override the default route. In MVC4, the routes are defined in App_Start/RouteConfig.cs. The "Default" route should be the LAST route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then, for your specific route, use the following BEFORE the default route:
routes.MapRoute(
name: "MyPage",
url: "my-page",
defaults: new { controller = "Page", action = "Index" }
);
Fianlly, ensure you have a controller PageController.cs with an action Index and a View Views/Page/Index.cshtml:
public class PageController : Controller
{
public ActionResult Index()
{
return View();
}
}