I am new to MVC ASP.NET and needed to call an action from one controller in an action of another controller. There I created object of controller and called my required action as below,
controllerOne co = new controllerOne();
co.requiredFunction();
but one of my senior advised me to not use this approach, which kills the MVC pattern use its given ActionInvoker.InvokeAction() function to call function of other controller and I am using now as below,
public class HomeController : Controller
{
this.ActionInvoker.InvokeAction(new System.Web.Mvc.ControllerContext(
this.ControllerContext.RequestContext, new controllerOne()),
"requiredAction");
}
This works fine, but I don't know if the way I am using ActionInvoker.InvokeAction() is correct. I searched to find any example but I could find any.
So my question is: Am I using it correctly?
To do this many people would create a service that encapsulates this requiredFunction and inject the service through it's interface into both controllers
use this
var ctrl= new MyController();
ctrl.ControllerContext = ControllerContext;
//call action
return ctrl.Action();
Related
In an asp.net MVC application, I need to produce some documens, HTML and PDF, which are not sent to the user's browser, but either sent by mail or entered in our document journalizing system. I produce these documents using Razor.
When a document is used only once, I just add a method to the relevant controller, and the view to that controller's view folder. This works. But I have a document that must be produced at two places in the application, implemented in separate controllers. I have made a new controller for this document with its own view folder.
My question is now: how do I call a method on this controller? Searching the web gives many answers, but all redirect the user to this document, which is not what I need.
You can just call it like you would any other method e.g.
public ActionResult DoSomething()
{
// Some code
var otherController = new OtherController(); // The other controller where the method is
otherController.CreatePdf(); // Call the method
// Continue with what ever else you need to do
return View(); // This will then return the `DoSomething` View
}
But personally it doesn't seem like this logic belongs in a controller. You should possibly think about refactoring this logic out of a controller and into a more logical place. Possibly create your own document generation class and use that.
If I'm getting you right.You could create a base controller and add the method there. You can inherit the Base controller in any controller where you want to call the method. here's a link that might help show you the use of Base controllers. How to wire common code from a base controller in ASP.NET MVC.
I have a question that I have been thinking about.
What happens from when I enter an URL in my browser and click enter to when the code in the corresponding controller actually executes?
Let's say I have an asp.net mvc application and a trivial Controller like this:
public class HomeController : Controller
{
public ActionResult About(int id = 25)
{
//code
}
}
So if I enter like myUrl/home/about?id=56 that controller gets invoked. I know there is a routing pattern like {controller}/{action}/{id} declared by default. But if an URL matches that pattern is a controller instance created then or what happens? Is there some Resolver class or similar? Is there like a List containing all the controllers so "Home" in the URL matches the HomeController?
I know the id parameter in the controller signature will be bound to the corresponding id value in the request context with the help of model binding. But there must be a lot of other magic happening here.
Hope someone can help a fresh confused asp.net mvc user
in a nutshell:
DefaultControllerFactory finds and instantiates the controller by its name using reflection (more info)
ControllerActionInvoker finds and invokes the action by its name using reflection (more info)
Good overall description can be found here.
Is it possible in ASP.NET MVC via some extension/override points to allow a "delegate field" to be used as an "action"?
Something like:
using System;
using System.Web.Mvc;
namespace Company.Web.Controllers
{
public class SwitchboardController : BaseController
{
public Func<ActionResult> Index, Admin, Data, Reports;
public SwitchboardController()
{
// Generic views
Index = Admin = Data = Reports =
() => View();
}
}
}
I know I'm a little hell-bent for this one but if this is possible it'd open up many new ways of making actions. You could, for example, have Django-style generic views in MVC with only a single line of code to define the action or have different ways to factor duplicate logic across multiple controllers.
I'm not quiet sure where would be the place to slap this logic into or how much work would be required to alter something so fundamental in the framework.
You will probably have to build your own Controller factory. This class builds controllers, and implements IControllerFactory. You can inherit from DefaultControllerFactory. Override CreateController() to return your own IController.
Register your controller factory in Application_Start() of MvcApplication using this line:
ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));
In your implementation of IController, override the Execute method. You can use the RequestContext to decide which delegate to invoke. It would probably be easiest to inherit from ControllerBase, and override Execute in there if you don't want to fully implement IController.
The RequestContext passed into Execute carries a RouteData object. This is a dictionary populated by the routing engine that tells you what action should be invoked, and any parameters. You can get the action name like this:
//context is a RequestContext object passed to IController.Execute()
string actionName = requestContext.RouteData.Values["action"];
You could even define your action as a dictionary, and just pull them out once you get the action name.
One last thing, normal action methods return an ActionResult, which the framework uses to decide which view to render. Once you execute your delegates, I think you'll have to set some stuff manually in your special base controller. I'm not exactly sure what to set or how to get your View executed from here without cracking open the MVC source.
Good luck! This looks like an interesting idea.
As you seem to be implementing a BaseController in your code sample, if you override the Execute (from the IController) you'll be able to interpret the request => action however you like.
No, it isn't. The base controller is looking for methods and not for fields to dispatch an action.
EDIT:
Sorry, I was a bit fast and fixed to the standard classes provided.
You can do that but you have to overwrite the Execute Method in your controller or implement and provide your own IActionInvoker to dispatch the action to fields. Look into the post action processing in detail. It explains the dispatching in detail.
Is it possible to add a .asmx file to an MVC project and have .asmx code call the controller and have the controller return data to the .asmx code?
Is it possible to add a .asmx file to
an MVC project
Yes.
asmx code call the controller and have
the controller return data to the
.asmx code?
Yes.
var controller = new YourController();
var httpContext = new HttpContextWrapper(this.Context);
var routeData = new RouteData();
var requestContext = new RequestContext(httpContext, routeData);
controller.ControllerContext = new ControllerContext(requestContext, controller);
var result = controller.YourAction();
But I discourage to do that. Instead move common logic into a separate service layer and use that one.
Unless you need functionality specific to the controller (such as rendered output, web context, etc), you could take out the logic you want to execute in the controller and put it in a new class and have both controller and webservice call the method in the new class.
You can call your asmx by adding an Ignore Route path in your global.asax RegisterRoute method
I can't answer the first part (though I assume it's possible), but the second part is simple.
It can of course access the controller because the controller is just a class with functions that return results. It will simply be a matter of setting the controller's HttpContext correctly, and then invoking the action method that you want. You can then do whatever you want with the ActionResult - render it to a string for instance.
I have a little question to community. Does ASP.NET MVC allow to execute an action of another controller without RedirectToAction() method and without creation of an instance of this controller?
This is impossible. For an instance method to execute there must be an instance to execute in. Action methods are simply methods like all other methods, so you always need an instance to call the method.
Do you mean you wish to have a View which returns nothing. No view. No nadda?
If so, u can return a EmptyResult ViewResult class...
HTH.
You can call it through the Reflection technic, But It's Not Recommended. Shortly because it's not in the request/response/controller context.
Personally, I prefer to have an internal static method(bla bla){...} and call it where ever i want.
But if you drop the
without creation of an instance of this controller
Clause, Then you can use this methodology. But as it explains, It's Not Recommended Too. the following is summarized:
var controller = new FooController();
controller.ControllerContext = new ControllerContext(this.ControllerContext.RequestContext, controller);
var jsonResult = controller.BlaMethod(someInputParams);