Routing to the actions with same names but different parameters - asp.net-mvc

I have this set of routes:
routes.MapRoute(
"IssueType",
"issue/{type}",
new { controller = "Issue", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Here is the controller class:
public class IssueController : Controller
{
public ActionResult Index()
{
// todo: redirect to concrete type
return View();
}
public ActionResult Index(string type)
{
return View();
}
}
why, when i request http://host/issue i get The current request for action 'Index' on controller type 'IssueController' is ambiguous between the following action methods:
I expect that first one method should act when there is no parameters, and second one when some parameter specified.
where did i made mistake?
UPD: possible duplicate: Can you overload controller methods in ASP.NET MVC?
UPD 2: due to the link above - there is no any legal way to make action overloading, is it?
UPD 3: Action methods cannot be overloaded based on parameters (c) http://msdn.microsoft.com/en-us/library/system.web.mvc.controller%28VS.100%29.aspx

I would have one Index method that looks for a valid type variable
public class IssueController : Controller
{
public ActionResult Index(string type)
{
if(string.isNullOrEmpty(type)){
return View("viewWithOutType");}
else{
return View("viewWithType");}
}
}
EDIT:
How about creating a custom attribute that looks for a specific request value as in this post StackOverflow
[RequireRequestValue("someInt")]
public ActionResult MyMethod(int someInt) { /* ... */ }
[RequireRequestValue("someString")]
public ActionResult MyMethod(string someString) { /* ... */ }
public class RequireRequestValueAttribute : ActionMethodSelectorAttribute {
public RequireRequestValueAttribute(string valueName) {
ValueName = valueName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
return (controllerContext.HttpContext.Request[ValueName] != null);
}
public string ValueName { get; private set; }
}

I ran into a similar situation where I wanted my "Index" action to handle the rendering if I had an ID specified or not. The solution I came upon was to make the ID parameter to the Index method optional.
For example, I originally tried having both:
public ViewResult Index()
{
//...
}
// AND
public ViewResult Index(int entryId)
{
//...
}
and I just combined them and changed it to:
public ViewResult Index(int entryId = 0)
{
//...
}

You can do it using an ActionFilterAttribute that checks the parameters using reflection (I tried it) but it's a bad idea. Each distinct action should have its own name.
Why not just call your two methods "Index" and "Single", say, and live with the limitation on naming?
Unlike methods that are bound at compile time based on matching signatures, a missing route value at the end is treated like a null.
If you want the [hack] ActionFilterAttribute that matches parameters let me know and I'll post a link to it, but like I said, it's a bad idea.

All you have to do is mark your second Action with [HttpPost]. For instance:
public class IssueController : Controller
{
public ActionResult Index()
{
// todo: redirect to concrete type
return View();
}
[HttpPost]
public ActionResult Index(string type)
{
return View();
}
}

Related

How to declare controller action method return type?

I understand ActionResult is the base class for RedirectResult class so essentially functionality for the code below is the same.
Is there an advantage to explicitly specify the appropriate result class as a return type as opposed to the base class?
public ActionResult Index()
{
return Redirect("Home/Contact");
}
public RedirectResult Index()
{
return Redirect("Home/Contact");
}
if you need redirect quickly to another action without lost any data and this action is in the same controller , call the action as a method:
public IActionResult Index()
{
return Contact();
}
public IActionResult Contact()
{
....
}
which one from another redirections methods is better is an opinion-based question and is not allowed by SO policy

Default controller and default action in MVC5

I have a website developed in MVC 5, I'm using route attributes for routing.
I've set the default controller and the default action for each controller using the following code
public class CompanyController : MainController
{
[Route("~/", Name = "default")]
[Route("Company/Index")]
public ActionResult Index(string filter = null)
{
//My code here
}
[Route("Company/Edit")]
public ActionResult Edit(int id)
{
//My code here
}
}
I've another controller with a default action :
[RoutePrefix("Analyst")]
[Route("{action=Index}")]
public class AnalystController : MainController
{
[Route("Analyst/Index")]
public ActionResult Index(string filter = null)
{
//My code here
}
[Route("Analyst/Edit")]
public ActionResult Edit(int id)
{
//My code here
}
}
The default controller worked perfectly, but when I navigate to the analyst controller without specifying the name of the action I get the following error:
Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL.
The request has found the following matching controller types:
SurveyWebsite.Controllers.AnalystController
SurveyWebsite.Controllers.CompanyController
How can I correct navigate to http://localhost:61534/analyst and reach the default action ( index) ? The action also should remain accessible by http://localhost:61534/analyst/Index
Thanks for your help.
Give an empty string as the route value for index action so that it works for Analyst, which is your controller route prefix. You can decorate with a second Route attribute for it to work with "Analyst/Index" url where you will pass "Index" to it.
[RoutePrefix("Analyst")]
public class AnalystController : MainController
{
[Route("")]
[Route("Index")]
public ActionResult Index(string filter = null)
{
//My code here
}
[Route("Edit/{id}")]
public ActionResult Edit(int id)
{
//My code here
}
}
This will work for both /Analyst and /Analyst/Index

How to create a controller action called 'event'

I need to add an action to my controller called 'event', but that's a reserved word. What's the easiest way to add an event action?
Eg:
public class entertainmentController : Controller
{
// GET: entertainment
public ActionResult Index()
{
return View();
}
// GET: entertainment/event
public ActionResult event() // <-- won't compile
{
return View();
}
}
Use the ActionName attribute
// GET: entertainment/event
[ActionName("event")]
public ActionResult EntertainmentEvent()
{
return View("EntertainmentEvent");
}
While I'd recommend against it, this will compile:
public ActionResult #event()
{
return View();
}
you can do that in route mapping. just add a route entertainment/event in RouteConfig and map that route to a custom action..lets say 'randomAction'

MVC multiple views for a single controller

Is it possible in MVC to do the following with a single controller "ListController" to take care of the following pages...
www.example.com/List/Cars/ForSale/{id} optional
www.example.com/List/Cars/ForRent/{id} optional
www.example.com/List/Search/
www.example.com/List/Boats/ForSale/{id} optional
www.example.com/List/Boats/ForRent/{id} optional
www.example.com/List/Boats/Search/
If not, is there any way to get around it besides making a CarsController and BoatsController separate? They will be using the same logic just would like the URLs different.
You can definitely do this. It is simple using routing. You can route the different urls to different actions in your controller.
Here are examples of defining some of the above urls:
routes.MapRoute("CarSale"
"/List/Cars/ForSale/{id}",
new { controller = "list", action = "carsale", id = UrlParameter.Optional } );
routes.MapRoute("ListSearch"
"/List/search",
new { controller = "list", action = "search"} );
routes.MapRoute("BoatSale"
"/List/Boats/ForSale/{id}",
new { controller = "list", action = "boatsale", id = UrlParameter.Optional } );
Then in your controller you would have action methods for each:
public ListController
{
// ... other stuff
public ActionResult CarSale(int? id)
{
// do stuff
return View("CarView");
}
public ActionResult BoatSale(int? id)
{
// do stuff
return View("BoatView");
}
// ... other stuff
}
Yes You can use multiple View in one Controller.
Let's take one Example,
I have one Controller Called Lawyers
public class LawyersController : Controller
{
// GET: Lawyers
public ActionResult Login()
{
return View();
}
public ActionResult Signup()
{
return View();
}
so I have one controller and 2 views.
Routes could also be specified above methods with decorators so no need for RouteConfig. You just need to omit the "controller/" part from the route.
public ListController
{
// ... other stuff
[Route("Cars/ForSale/{id}")]
public ActionResult CarSale(int? id)
{
// do stuff
return View("CarView");
}
[Route("Boats/ForSale/{id}")]
public ActionResult BoatSale(int? id)
{
// do stuff
return View("BoatView");
}
// ... other stuff
}

Accessing ASP.NET MVC Action Parameters

This must be simple, but I can't seem to figure it out. I am setting an action parameter inside an action filter as follows:
public class MyFilter : ActionFilterAttribute
{
public override void OnActionExecuting (ActionExecutingContext filterContext)
{
filterContext.ActionParameters["MyParam"] = "MyValue";
}
}
I am applying the filter to an entire controller as follows:
[MyFilter]
public class HomeController : Controller
{
public ActionResult Index()
{
// How do I access MyParam here?
return View();
}
}
}
How do I access MyParam inside an action method?
Maybe you could use:
[MyFilter]
public ActionResult Index(string MyParam)
{
//Do something with MyParam
return View();
}
You can decorate whole controller with [MyFilter] or only one action.
I'm hoping this will work:
var myParam = ValueProvider.GetValue("MyParam").RawValue as string;
Since ValueProvider is what modelbinders use to get the values I would think it should be able to get the value set in your filter.

Resources