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.
Related
I suspect someone will call this a duplicate....I have looked through the examples that I have seen and tried to implement the suggested changes but I am still having this issue. In my index view, I have an ActionLink HTML Helper to redirect to an Edit. When I mouse over it, it shows the URL target as:
http://localhost:58028/Instruments/Edit?InstrumentId=1
Instead of the desired
http://localhost:58028/Instruments/Edit/1
I have built a "for comparison" scaffolded situation and it appears to me that I am doing the exact same thing, yet it is resulting in the proper URL. When I debug and stop in the Edit routine of the controller, it shows me that it is using the correct (and only) mapping.
Can someone please tell me what I am missing:
Here's my View code:
<td>#Html.ActionLink(item.Description, "Edit", new { InstrumentId = item.InstrumentId })</td>
Here's my Controller code:
public ActionResult Edit(int? InstrumentId)
and here's my routing:
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 }
);
}
Your default route expects a parameter named id, so to use the default route, change the link to
#Html.ActionLink(item.Description, "Edit", new { id = item.InstrumentId })
and the method to
public ActionResult Edit(int? id)
or create a specific route for your method that includes a placeholder for a parameter named InstrumentId and place it before the default route
routes.MapRoute(
name: "InstrumentEdit",
url: "Instruments/Edit/InstrumentId",
defaults: new { controller = "Instruments", action = "Edit" }
);
routes.MapRoute(
name: "Default",
....
Both options will generate ../Instruments/Edit/1
try changing the Html Helper to this
#Html.ActionLink(item.Description, "Edit", new { id = item.InstrumentId })
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'd like to understand how to set routing parameters to do the follow: when user call shortened url like http://hostname.com/shortenedurl my asp.net mvc project should call action and parameter like http://hostname.com/controller/action
Never before I did something like that so I will be appreciate for any advise. How code and decode url string from normal to short and back I know already.
You can define specific routes in RouteConfig.cs file. For example, .../MyShortUrl will route to the Edit method of EmployeeController
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "MyShortUrl",
url: "MyShortUrl",
defaults: new { controller = "Employee", action = "Edit", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Note specific routes need to placed in order before more general routes
There is no "normal" and "short". It would be best if you used Routing. It's important to read some introduction to Routing to understand how it works.
(I don't think an extract would be appropriate here since the whole article needs to be read and its concepts understood.)
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();
}
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.