Run once for request where is the best place? - asp.net

Hi I have some codes that need to run for 1 time for a request. I have a BaseController which all controllers derived from. I write my code to BaseController onActionExecuting method but it is not good because for every action execution code is running. I can prenvent it with a basic if clause but i dont want to use it like that.
What is the best place for run a code 1 time for a request. I also want to reach HttpContext where i write this code. thanks

After your comment about child actions you could test if the current action is a child action and don't execute the code. So you could have a custom action filter:
public class CustomFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// this method happens before calling the action method
if (!filterContext.IsChildAction)
{
// this is not the a child action => do the processing
}
base.OnActionExecuting(filterContext);
}
}
and then decorate your base controller with this custom attribute. Similar test could be performed in the overridden OnActionExecuting method of your base controller if you prefer it instead of action attributes:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.IsChildAction)
{
// this is not the a child action => do the processing
}
base.OnActionExecuting(filterContext);
}

Related

Prevent a ASP.NET MVC global filter from being applied on Elmah action

I'm using Elmah for logging exceptions on my MVC application using Alex Beletsky's elmah-mvc NuGet package.
The application registers some global filters, applied on each action called.
Is there a way to prevent some of those filters from being applied when calling the Elmah.Mvc.ElmahController error log page (foo.com/elmah) ?
A test like below works, of course, but I'm looking for a more elegant way that would not involve modifying the filter (nor the source code from Elmah / Elmah MVC). Is it even possible ?
public class FooAttribute : FilterAttribute, IActionFilter
{
// ...
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.Controller is ElmahController)
{
return;
}
// do stuff
}
}
I know that attributes can't be added or removed at runtime.
I thought of wrapping the ElmahController in a new one where I could add an exclusion filter, but I'm not sure how (if possible) to change the web.config to reference this wrapper instead of the original controller.
You could register your global filters through a custom IFilterProvider:
public class MyFilterProvider : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
if (controllerContext.Controller is ElmahController)
{
return Enumerable.Empty<Filter>();
}
return ... the collection of your global filters
}
}
and in your Application_Start instead of calling:
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
you would call:
FilterProviders.Providers.Add(new MyFilterProvider());

How to register delegating handlers in a MVC Application? (not Web API)

How do I register a global message handler in a MVC application?
I tried registering it in my Global.asax.cs, but this handler never gets called whenever I access any of my endpoints in all my controllers that inherit from System.Web.Mvc.Controller.
However, it does get called when I access routes all my controllers that inherit from System.Web.Http.ApiController.
This is what I put in my Global.asax.cs:
protected void Application_Start()
{
//other initializing stuff here
**GlobalConfiguration.Configuration.MessageHandlers.Add(new AuthenticationHandler());**
}
I believe you're looking for Filters. You could build something like this:
public class MyAuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// do your work here
}
}
and then add it to the global filters list in Application_Start:
GlobalConfiguration.Configuration.Filters.Add(new MyAuthorizationFilter());

MVC Web .Net: Intercept all calls before reaching controller?

I have a .Net MVC web application (Not WebAPI), and I want to intercept all calls to the web app before they reach the controller, check for a value in the request headers, and do something if the value isn't present (such as presenting a 404). What's the ideal way to do this? Keep in mind this is not a Web API application, just a simple web application.
Depending on what specifically you want to do, you could use a default controller which all other controllers extend. That way you can override OnActionExecuting or Initialize and do your check there.
public class ApplicationController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
//do your stuff here
}
}
public class YourController : ApplicationController
{
}
You're looking for global action filters.
Create a class that inherits ActionFilterAttribute, override OnActionExecuting() to perform your processing, and add an instances to global filter collection in Global.asax.cs (inside RegisterGlobalFilters())

Executing code before any action

I have the following requirement:
On every request to my web page, regardless of which action the user is trying to invoke, I need to call some code that checks if a resource is in place. If it is, then everything is fine and the action method should be called as normal.
However, if this resource is not available, I want all requests to return a separate page asking the user to select another resource from a list of available ones.
So is it possible to have one method run before any action method that have the option of cancelling the call to the action method, and doing something else instead?
Look at global action filters (available since asp.net mvc 3): http://msdn.microsoft.com/en-us/library/gg416513%28v=vs.98%29.aspx
Basically, in your Global.asax, you can register the filter globally during your application startup (in Application_Start()) with:
GlobalFilters.Filters.Add(new MyActionFilterAttribute());
You can then override the OnActionExecuting method, and set the Result property with a RedirectToRouteResult.
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (IsMyResourceAvailable())
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary {
{ "Controller", "YourControllerName" },
{ "Action", "YourAction" }
});
}
base.OnActionExecuting(filterContext);
}
MVC provides several hooks to do this.
In a base controller, you can override Controller.OnActionExecuting(context) which fires right before the action executes. You can set context.Result to any ActionResult (such as RedirectToAction) to override the action.
Alternatively, you can create an ActionFilterAttribute, and exactly like above, you override the OnActionExecuting method. Then, you just apply the attribute to any controller that needs it.

How do you interrupt/intercept MVC Actions using ActionFilters?

Feel free to close this one if it s a duplicate. I couldn't find an answer.
I wish to be able to place a System.Web.ActionFilterAttribute on an Action Method and override the OnActionExecuting method to insert business logic which determines if the Action should be fulfilled.
Can the ActionExecutingContext be used to cancel the executing Action Method and do one of the following:
Send an HTTP Status Code (and the corresponding <customError> page).
Execute a different Action Method within the same Controller.
Send an HTTP Status Code (and the
corresponding <customError> page)
Almost:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = 500;
}
Execute a different Action Method
within the same Controller.
Yes:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Result = new ViewResult() { ViewName = "SomeOtherAction" };
}
You can always redirect to another controller/action in an action filter.
See here for an example.

Resources