How to Duplicate an Action in same Controller using MVC - c#

I have 2 actions in one controller
public ActionResult DoSomething()
{
...
}
public ActionResult SoSomethingAgain()
{
...
}
I would like to have both requests go to the same action.
perhaps an alias....
[ie. SoSomethingAgain]
public ActionResult DoSomething()
{
...
}
What is the proper approach?

If I'm reading this correctly you can just do:
public ActionResult DoSomething()
{
...
}
public ActionResult SoSomethingAgain()
{
return DoSomething();
}

In SoSomethingAgain just do this:
return DoSomething();
The only other option you have would be to build a specific Route for that controller when you setup routes at the start of the application. That's going to be a lot more work than it's worth.

If SoSomethingAgain is the called action then the two earlier answers will run the code that is inside DoSomething, but the controller action and context is still SoSomethingAgain. This means that a return View() statement inside the DoSomething would look for a SoSomethingAgain view.
Similarly the pipeline would use filters defined on SoSomethingAgain, and not those on DoSomething. You can see this if you put an [Authorize] filter on DoSomething. If you hit the DoSomething action you will be prompted to log in, but if you hit the SoSomethingElse action you will not be prompted.
Maybe that's what you want, maybe not. If it isn't and you want to have both a DoSomething url and a SoSomethingElse url, but both running the same code, then get rid of the SoSomethingElse controller action, and add a custom route (before the default route).
routes.MapRoute(
name: "SoSomethingAgainRoute",
url: "{controller}/SoSomethingAgain/{id}",
defaults: new { controller = "Home", action = "DoSomething", id = UrlParameter.Optional }
);

Related

How to redirect to action when action contains route attribute

Controller
public class TestController{
[Route("TestIndex")]
public ActionResult Index(){
}
}
html
Go to test
I have above code!!
On Go to test click I want to redirect to Index action of Testcontroller for that I used below code
href="#Url.Action("Index","TestController")"
but I think as route attribute is used there that's why it is not redirecting to that action
Thank you in advance
you have a bug in your code, should be
Go to test
or maybe
Go to test
You have to use something one - absolute route, or relative. Since you didnt post a controller route and your config endpoints, I can not understand what route you really need, but try this, it will certainly work
Go to test
and route
[Route("~/Test/TestIndex")]
public ActionResult Index(){
}
ASP.NET has built in methods for this such as RedirectToAction See https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.controller.redirecttoaction?view=aspnet-mvc-5.2
A usage would look like:
return RedirectToAction("controller", "method");
To pass route attributes simply use:
return RedirectToAction("controller","method", new { id });
If that doesn't work either try using:
RedirectToAction with parameter
return RedirectToAction( "Main", new RouteValueDictionary(
new { controller = controllerName, action = "Main", Id = Id } ) );
As some people have noted the other example not working for them.

AreaRegistration MapRoutes for Help Docs

I have an api using web api 2 and I am trying to create help docs within an Area so that an incoming request like ...api/people.help will route to the people controller and people view and serve up the html. I am struggling with the route mapping for the area after refactoring the code. Previously, I had routes like this:
public override void RegisterArea(AreaRegistrationContext context) {
context.MapRoute(
name: "Help",
url: "{action}.help",
defaults: new { area = "help", controller = "default" }
);
All the methods were in the default controller and this worked. Now, I need a separate controller for each resource (eg people, schedules etc) but can't get the routes to work. I would appreciate help, I am very new to this. How do I get each help request to map to the controller with the same action name?
Wouldn't it simply be something similar to:
public override RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Help",
url: "api/{controller}.help",
defaults: new { area = "help" }
);
}
What you have in your post is a default for the name of the controller, in this case, it's name will always be default. Instead, what you're looking for is that when someone routes to your controller name suffixed with .help, it'll route to a path akin to api/help/people, which will end up calling a default action (in MVC) such as index.cshtml or the default action for a GET request to the controller (for WebAPI).
So, you want to set the default area to help as shown above. You also want to set the default action that should execute on the provided controller.
Update: To answer question in comment
For MVC, you can have an action method whose name matches what the controller name will be in the URL:
public class PeopleController : Controller
{
[HttpGet] // Not strictly necessary, but just want to stress this is GET
public ActionResult People()
{
// Do stuff in your action method
}
}
The only problem is, your action method will be different for each controller, and so unknowable for route registration purposes. Therefore, you should maybe have just a default Help action:
public class PeopleController : Controller
{
[HttpGet]
public ActionResult Help()
{
// Do stuff
}
}
Then you can have the following route:
public override RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Help",
url: "api/{controller}.help",
defaults: new { area = "help", action = "Help" }
}
You could take this one step further and provide a Help method in a custom base controller class:
public class MyBaseController : Controller
{
public virtual ActionResult Help()
{
// Do default behavior stuff, if appropriate
}
// If you don't have any "default" behavior, you could make the method abstract:
// public abstract ActionResult Help();
}
public class PeopleController : MyBaseController
{
public override ActionResult Help()
{
// Do stuff.
}
}
Update to further answer OP's question in comments
So, now the OP is saying: "but I want my view to have the same name as my controller." Ok, that should be no problem:
public class PeopleController : MyBaseController // if you're using a base class
{
public override ActionResult Help()
{
return ViewResult("People");
}
}
So, you can have a view with any name you want. But if the view's name differs from the name of the action method, then when returning (say) a ViewResult, you'll need to specify the name of the view to return.
Having said all that, the default folder structure for views in ASP.Net is Areas/{AreaName}/Views/{Controller}/{viewname}.{cs|vb}html. And here, {viewname} is by default assumed to be the action method name, but doesn't have to be when, as above, explicitly telling MVC which view to return (in the example above, People.cshtml).
HTH.

The resource cannot be found error for MVC 3

I know there are a lot other topics like this, but from what I found, and did accordingly to the answers - I still have the error.
The Global.asax:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Func", action = "Main", id = UrlParameter.Optional } // Parameter defaults
);
The Controller:
public class FuncController : Controller
{
//
// GET: /Func/
public ActionResult Main()
{
return View();
}
public ActionResult Products()
{
return View();
}
And accordingly the 2 .cshtml View files with the Main and Products names.
In the "Project Properties->Web" I selected "Start URL" with value "http:// localhost:63497/Main". I don't get it where might the problem be, as in the other topics I found about this error, the problem was always in some of these things. But now, everything seems to be fine, and still - error.
Main is the Action method. You need to navigate to the Controller and let that hit the appropriate Action. Try navigating to:
http:// localhost:63497/Func/Main
Which is Func Controller. ActionMethod Main
try like this..
http://localhost:63497/Func/Main.
because the route is from controller to ActionResult.
so, here Func is the Controller and the Main is your ActionResult Method.
so, you have to use the controller first in url before the Action Method.

How to name/divide controllers in MVC3 application

At the moment I have 3 controllers: Home, Summary and Detail
However, each has only one action: Index, Display and Display respectively.
This smell bad to me.
I was hoping to use the MapRoute to allow:
myapp/Home
myapp/Summary/prop1/prop2
myapp/Detail/prop1/prop2/prop3
instead of
myapp/Home
myapp/Summary/Display/prop1/prop2
myapp/Detail/Display/prop1/prop2/prop3
and thereby miss out the "Display" part...but again, this doesn't smell right. Although it works, it means manually adding links instead of using Html.ActionLink(...)
Would it be better to have Home/Index, Home/Summary and Home/Detail all in one controller?
I was hoping to provide a simple URL structure so users who know what they are doing could simply type it in as above...the "Home" part seems wasted?
I agree with #Tim that you should use a single controller. A controller is a logical grouping of actions; for example the CRUD operations for Foo. NerdDinner is a good example of this.
I disagree with the routes. You can do whatever you want with the routing; but it should be meaningful to the user. You probably just have a single catchall route similar to the one below.
routes.MapRoute("Default", //RouteName
"{controller}/{action}/{id}", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Index",
id = UrlParameter.Optional}
)
You can have the routes you want by using a single controller.
Your desired urls:
myapp/Home
myapp/Summary/prop1/prop2
myapp/Detail/prop1/prop2/prop3
The controller setup:
public class HomeController : Controller
{
public ActionResult Index() { ... }
public ActionResult Summary() { ... }
public ActionResult Details() { ... }
}
The routing setup:
routes.MapRoute("Home-Index", //RouteName
"myapp/Home", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Index"});
routes.MapRoute("Home-Summary", //RouteName
"myapp/Summary/prop1/prop2", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Summary",
prop1 = UrlParameter.Optional,
prop2 = UrlParameter.Optional});
routes.MapRoute("Default", //RouteName
"{controller}/{action}/{id}", //RouteUrl
new { //RouteDefaults
controller = "Home",
action = "Index",
id = UrlParameter.Optional}
)
Now there are a few important things to note:
Routing works like a switch statement, the first url that matches is
the one it will use, that's why you have the catchall as the last
one.
The url defined in your map route can be whatever you want. It
doesn't have to match with the controller, because once you remove
the placeholders ({controller}, etc) it uses the default for
navigation. So the Home-Index route url could be myapp/foo/bar/baz
and id would still take you to the Home index action.
The placeholders work automagically. I have not been able to find a good resource explaining how the default route works.
Hope this helps.
Not sure if I totally get your question, but what about creating a base controller class that inherits from Controller, and have your shared actions there instead? That way you don't need to repeat yourself as much.
You need only one controller and inside it multiple actions..
public class HomeController : Controller
{
public ActionResult Index()
{
}
public ActionResult Summary()
{
}
public ActionResult Details()
{
}
}
In the action link
#Html.ActionLink("Details", "Details","Home");
that's enough, no need to add multiple controller..
Hope these helps..
You can pretty much go down any route you want when it comes to this, all just depends on what you want to achieve.
You can stick all the actions in the Home controller so your routes would be
myapp/Home
myapp/Home/Summary/prop1/prop2
myapp/Home/Details/prop1/prop2/prop3
In this option you have 1 controller, 3 actions, with 2 additional routes to handle the URls
It depends on what the summary and details are of though? Like if it is the summary of an order, i would prefer
myapp/Orders/Summary/prop1/prop2
myapp/Orders/Details/prop1/prop2/prop3
In this you would have your Home controller and the Index action, then an Orders controller with two actions. I would say that Summary and Details would generally suggest that you are displaying something anyway, so you would not need the "Display" part as you have in your suggestions.
If you want your URLS to be
myapp/Home
myapp/Summary/prop1/prop2
myapp/Detail/prop1/prop2/prop3
Then you make 3 controllers
HomeController
SummaryController
DetailController
Each of these will have 1 Action
public ActionResult Index() {
}
For the SUmmary and Detail controller you will just pass in some extra paramaters to the Index action

Using the ASP.NET MVC Attribute Based Route Mapper

In my ASP.NET MVC application, I want to use this ASP.NET MVC Attribute Based Route Mapper, first announced here.
So far, I understand how to implement code that uses it, but I've run into a few questions that I think those who have used this attribute-based route mapper in the past will be able to answer.
How do I use it with ActionResults that are for HTTP POSTs? In other words, how does it work with form submissions and the like? Should I just put the URL of the GET method in, or should I use the GET method URL without any parameters (as in HTTP POST they aren't passed in through the URL)?
How do I use it with "URL querystring parameters"? Can the attribute be configured to map to a route such as /controller/action?id=value rather than /controller/action/{id}?
Thanks in advance.
How do I use it with ActionResults
that are for HTTP POSTs?
You decorate the action that you are posting to with the [HttpPost] attribute:
[Url("")]
public ActionResult Index() { return View(); }
[Url("")]
[HttpPost]
public ActionResult Index(string id) { return View(); }
If you decide to give the POST action a different name:
[Url("")]
public ActionResult Index() { return View(); }
[Url("foo")]
[HttpPost]
public ActionResult Index(string id) { return View(); }
You need to supply this name in your helper methods:
<% using (Html.BeginForm("foo", "home", new { id = "123" })) { %>
How do I use it with "URL querystring
parameters"?
Query string parameters are not part of the route definition. You can always obtain them in a controller action either as action parameter or from Request.Params.
As far as the id parameter is concerned it is configured in Application_Start, so if you want it to appear in the query string instead of being part of the route simply remove it from this route definition:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoutes();
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index" }
);
}

Categories

Resources