Can we create Static ActionResult method in Controller? - asp.net-mvc

Someone ask following question to me in interview, to which I cannot able to answer. Somebody please help me.
Can we create Static ActionResult method in controller?
If yes. What is the benifits? and if no. What is the reason?

If "ActionResult method" is a method that returns ActionResult, you can declare it static, of course, but it will not be called when you initiate that action. When calling some action, ASP.NET MVC creates an instance of the controller (using ControllerFactory), and since your method is static, it is not related to any instance, and thus, it will not be called by MVC

Don't think it is a good idea to create a static action method, as you will no longer have access to all the controller properties, such as controllercontext, etc.

Related

ASP.NET MVC: Uses a delegate field as an action method?

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.

Execute action without redirect

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);

How can I generate a URL within a shared (static) method in MVC.NET?

I'm creating a Shared (static) method in ASP.NET MVC so it can be used by any controller in my project. This static method needs to generate a URL. I think I need to use System.Web.Mvc.UrlHelper, but I can't figure out how to call it from within a static method. The constructor seems to want a RequestContext. Any ideas?
AFAIK, there is no way to get the "current" RequestContext statically. You'll need to pass in the RequestContext from the controller that's calling it. Any controller can do that by just using this code:
this.ControllerContext.RequestContext

Asp.Net MVC Beta: Previous RouteData overrides current RouteData?

I have something similar to the following method:
public ActionResult Details(int id)
{
var viewData = new DetailsViewData
{
Booth = BoothRepository.Find(id),
Category = ItemType.HotBuy
};
return View(viewData);
}
and the following Route:
routes.MapRoute("shows","shows/{controller}/{action}/{id}", new {id = 0});
Everything worked fine before the Beta, when I had Preview 3. Now the method will fill the id correctly the first time I execute the action. However the second time the controller's ModelState contains the last-use id value. This causes the ActionInvoker to use it in the method's parameter instead of the Route value.
So if I call the action twice on two different entities the results are such:
www.mysite.com/shows/Booth/Details/1 => Details(1)
www.mysite.com/shows/Booth/Details/2 => Details(1) //from ModelState["id"]
From my quick scan with Reflector it seems it first binds parameters to the ModelState then to Routes. However, I never even posted anything from the model. As far as I can tell the ModelState should not contain anything.
Is this a bug in the Beta, possibly a bug somewhere in my code, or is there some design feature that I am ignorant of? Any insight into the nature of ModelState and why this happens is appreciated.
EDIT:
I discovered that this issue is actually a symptom of what appears to be a bug with the DefaultValueProvider if you instantiate a Controller from an IoC container that exists for the lifetime of the Asp.Net application.What happens is that the DefaultValueProvider uses the first ControllerContext given to the Controller and never updates it until the controller is recreated. This causes old RouteData to be used for method parameters instead of the current RouteData.
It's hard for me to tell what you expect to happen and what is happening from your post. Is it possible there's an error in your BoothRepository.Find method such that it returns the same thing every time?
ModelBinder should not be affecting this method because the parameter to the action method is a simple type, int.
Were both of these requests GET requests? If you still are having problems, can you try and create the simplest repro possible and email it to philha - microsoft dot com?
EDIT: The problem ended up being that the developer was attempting to re-use the valueprovider across requests (by having Castle Windsor manage the lifecycle of Controllers). Right now, there's no support for re-using controller instances across requests like you would with IHttpHandler which has a IsReusable property. So in general, reusing controllers across requests requires doing a lot more work on your end. :)
The problem is the LifeStyle, I completetly overlooked the fact it was being defined, which means by default the controllers will use the Singleton lifestyle. Setting the LifeStyle to Transient for all controllers will sort this problem.
if you use spring.net modify
Controller's singleton to "false"
This is a common issue when using Singleton behavior with a IoC container such as Spring.NET or Windsor. Controllers should not have singleton behavior because the ControllerContext is per request, much like HttpContext.

passing viewdata to asp.net mvc masterpages

I'm trying to pass ViewData to my asp.net mvc masterpage for an mvc usercontrol that I keep on a masterpage. For example, I created a dropdownlist of names as an mvc usercontrol and I put that in my masterpage.
The problem I am running into is passing the ViewData to the masterpage. I found this article from Microsoft which has a decent solution but I was wondering if there are other "better" solutions out there. The thing I don't like about the solution in the link is that I have to change every controller to inherit from a new controller class.
http://www.asp.net/learn/MVC/tutorial-13-cs.aspx
Edit: The problem I am looking at is the fact that if I place a user control in my masterpage that relies on ViewData, I have to REPEATEDLY include that ViewData for every single page that uses said masterpage. It's possible the solution in the link above is the best solution but I was hoping there were other alternatives.
The master page already has access to the ViewData. If you want strongly typed access to it, you need to do two things:
Put the master page stuff in a base class (e.g. CommonViewData)
Have you master page inherit from the generic ViewMasterPage<> class:
" %>
Could you possibly use the OnActionExecuting method on a base controller class and populate the view data there?
Something like:
protected override void OnActionExecuting(ActionExecutingContext context)
{
context.Controller.ViewData.Model = GetDataForControl();
}
I haven't tried it so it's just a thought...
For what it's worth, I am using the method from that tutorial in a current project and it works very well.
What you can also do, if it is data that is somewhat static (like a menu that doesn't change much), is to put the object on the cache so your database isn't called for every controller initialisation.
I usually use an abstract controller class for my MasterPage, it is the best solution, because the MasterPage is like an "abstract view". But I override the MasgerPageController View() method to include the viewdata.
protected override ViewResult View(string viewName, string masterName, object model)
{
this.ViewData["menu"] = this.PagesRepository.GetPublishPages();
return base.View(viewName, masterName, model);
}
I don't quite get your problem...
The problem I am looking at is the fact that if I place a user control in my masterpage that relies on ViewData, I have to REPEATEDLY include that ViewData for every single page that uses said masterpage.
Well yeah... of course you do. If you have a usercontrol in your master page then of course you're going to have to pass the required data for that usercontrol for every action & view that uses that masterpage.
It's not like you have to repeat yourself if you are just inheriting from a base controller.
Is your issue the fact that some controllers have actions that both do and don't call views that derive from that particular masterpage? So therefore if you are implementing a base controller, the actions that don't use that particular masterpage will still have the viewdata for it...? (If all that makes sense ;-)
I think the solution suggested does work but not the ideal solution. If we put the code in the BaseController constructor it is going to be called even for Action methods which does not have a MasterPages (e.g Post methods and Ajax methods).
I think a better solution(not ideal) is to call Html.Action method in the Master page.

Resources