Handle differently GET and POST during OnActionExecuting - c#

During the OnActionExecuting method, some processing are made which could lead to a redirection to the home page.
But in Ajax POST calls, these processing will definitely fail. Calls are made by a grid from Kendo UI, so I have no control on them.
So I want this method handles in two different ways if calls are GET and POST.
I tried :
[HttpGet]
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Do something
}
[HttpPost]
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Do nothing
}
But it does work.
I can't find a Property like IsPostBack in WebFroms.

The ActionExecutingContext has a HttpContext property. From there, you can obtain the Request property, which has a HttpMethod property
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if(filterContext.HttpContext.Request.HttpMethod == "POST")
{
// Do nothing
}
else
{
//Do Something
}
}

Related

OnActionExecution on BaseController and Particular Controller

I have a BaseController which is like below.
public class BaseController : Controller
{
public string BDynamicConnectionString { get; set; }
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Getting dynamic connectionstring
this.BDynamicConnectionString = GetDynamicConnetionString(this.BCCompanyId, this.BCCompanyIdentifier);
}
}
I have inherited this base controller in my controller as below.
public class TestController : BaseController
{
private ClassroomBL objClassroomBL;
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
this.objClassroomBL = ClassObjects.ClassroomBLObject(BDynamicConnectionString);
}
public ActionResult FetchDefaultStatuses()
{
this.objClassroomBL.FetchDefaultStatuses(145);
return View();
}
}
As it is visible I have OnActionExecuting(ActionExecutingContext filterContext) on both BaseController and TestController.
Actually Why I did it like this is I am managing many things in base controller which are needed in each controller inherited from this.
But now I need something like OnActionExecuting(ActionExecutingContext filterContext) on particular controller because I have to initialize object before calling action and object which I have to initialize it uses a property which is initialized in BaseController.
If I am adding OnActionExecuting(ActionExecutingContext filterContext) on both then first, controller which is inheriting BaseController on this event fires before the BaseController. I know this happening because of OOPS concept.
Is anything else I can add on Controller which fires after Basecontrollers OnActionExecuting but before action execution of particular controller .
Thanks!
Just use following in the first line of overrided method:
base.OnActionExecuting(filterContext)
See also base keyword.

MVC ActionFilterAttribute but only on main View

I have an attribute on my Controller
[ABC]
MyController
The Attribute checks something but I only want to check once per page.
public class ABCAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
////Do some check
}
The OnActionExecuting fires for every element on the page. Partials etc.
How do I check to see if the filterContext is the main page and not a child resource on the page?
public class VerificationAttribute : ActionFilterAttribute
{
public VerificationAttribute ()
{
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//We don't care about children/partials
if (filterContext.IsChildAction)
return;
}
Ignore, think I miss read your question

Combining AjaxOnlyAttribute and ChildActionOnlyAttribute into one action filter

I want to be able to mark an action on controller to be called both from ajax calls and via RenderAction. The problem is that both this attributes derive or implement different abstractions. One way out is the next:
[AjaxOnly]
PartialViewResult GetViewAjax(int foo) { return GetView(foo); }
[ChildActionOnly]
PartialViewResult GetView(int foo) { ... }
But this is not neat at all.
The AjaxOnly attribute I am talking about is:
public sealed class AjaxOnlyAttribute : ActionFilterAttribute
{
#region Public members
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext == null)
throw new ArgumentNullException("filterContext");
if (filterContext.HttpContext.Request.Headers["X-Requested-With"] != "XMLHttpRequest")
filterContext.Result = new HttpNotFoundResult();
}
#endregion
}
This method is taken from MVC3 futures. An important comment why the condition is not filterContext.HttpContext.Request.IsAjaxRequest() was made by dev team and says the following:
// Dev10 #939671 - If this attribute is going to say AJAX *only*, then we need to check the header
// specifically, as otherwise clients can modify the form or query string to contain the name/value
// pair we're looking for.
This doesn't make any sense. Those 2 attributes are mutually exclusive. If an action is marked with [ChildActionOnly] it can never be directly accessed by the client using an HTTP request (be it synchronous or asynchronous). So if you want an action to ever be accessible using AJAX, you should never decorate it with the [ChildActionOnly] attribute.
I don't know what this [AjaxOnly] attribute is and where it comes from but depending on how it is implemented you might need to tweak it in order to allow child action requests if it relies only on the Request.IsAjaxRequest() method. For example if it is something like this:
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new HttpNotFoundResult();
}
}
}
you might want to tweak it like this:
public class AjaxOrChildActionOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest() &&
!filterContext.IsChildAction
)
{
filterContext.Result = new HttpNotFoundResult();
}
}
}
Inspired on Darin's answer and ChildActionOnlyAttribute's source code, this is the solution I have come up with, which I think it's a tiny bit better:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AjaxOrChildAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
return controllerContext.IsChildAction || controllerContext.RequestContext.HttpContext.Request.IsAjaxRequest();
}
}
This way, the validation is done before even trying to execute, and the error you get if you type in the url is the exact same one as trying any invalid url.

Executing code before a controller's method is invoked?

Is it possible to make an action filter or something that runs before the action method itself runs on the controller?
I need this to analyze a few values in the request before the action runs.
You can override OnActionExecuting method in controller class
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
//Your logic is here...
}
You could use an attribute:
public class MyFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Your logic here...
base.OnActionExecuting(filterContext);
}
}
And if you want to apply it to all controllers, in your Global.asax.cs:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyFilterAttribute());
}
protected void Application_Start()
{
// Other code removed for clarity of this example...
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
// Other code removed for clarity of this example...
}
If u don't want to use a base controller u can also add a own HttpHandler and register it in the web.config. In the BeginProcessRequest method u can analyse the values.

ActionFilter not firing after setting result in controller.OnActionExecuting

I have a global action filter that is setting the MasterPage of all ViewResults during the OnActionExecuting event.
In a number of my controllers (where each controller represents a feature of the application) I need to check to see if the feature is enabled and if not, return a different View.
Here's the code:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!settings.Enabled)
{
filterContext.Result = View("NotFound");
}
base.OnActionExecuting(filterContext);
}
The problem is that when setting the result like this, my ActionFilter's OnActionExecuted method does not fire, meaning I do not get the correct MasterPage applied.
I would like to understand why this happens. One remedy is to move my ActionFilter logic into OnResultExecuting (this does fire), but I am still confused as to why OnActionExecuted does not.
Many thanks
Ben
If you assign a result to the filterContext.Result inside an OnActionExecuting then the action won't execute => the OnActionExecuted will never run. So you might need to apply the correct master page inside the OnActionExecuting event when returning the NotFound view:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!settings.Enabled)
{
// Because we are assigning a Result here the action will be
// short-circuited and will never execute neither the OnActionExecuted
// method of the filer. The NotFound view will be directly rendered
filterContext.Result = new ViewResult
{
ViewName = "NotFound",
MasterName = GetMasterName()
};
}
}
As an alternative how about assigning the master page (layout) in _viewstart.cshtml and not worry about the filter?

Categories