i have the following base controller...
public class BaseController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
if (something == true)
RedirectToAction("DoSomething", "Section");
base.Initialize(requestContext);
}
}
Basically, all my controllers will derive from BaseController, and it will redirect them if a certain value is true. However, this code does not work!!! The call to RedirectToAction is made, but after the Initialize method is finished, it will just move on to the originally called controller.
Does that make sense??
Many thanks,
ETFairfax.
I think you are overriding wrong method. Try with OnActionExecuting or OnActionExecuted.
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (something == true)
filterContext.Result = RedirectToAction("DoSomething", "Section");
else
base.OnActionExecuting(filterContext);
}
I'm not sure if this is what you want, but try this:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
if (something == true)
RedirectToAction("DoSomething", "Section");
else
base.Initialize(requestContext);
}
Related
In my project I use the OutputCache attribute so my web server doesn't have to keep downloading the same files, but rarely there are some issues where for unknown reasons it returns null.
So If the result is null I don't want to cache the result is there a simple way to do this?
[OutputCache(VaryByParam = "path", Duration = 6000)]
public ActionResult LoadCachedFile(string path)
{
var result = DownloadFile(path);
return result;
}
You would have to create a class inheriting from OutputCacheAttribute overriding the
OnActionExecuted(System.Web.Mvc.ActionExecutedContext filterContext)
method. Here's a little sample code:
[System.AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
sealed class CustomOutputCacheAttribute : OutputCacheAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result != null)
base.OnActionExecuted(filterContext);
}
}
I had to do something similar to what nikstffrs suggested, but instead of overriding OnActionExecuted I used OnResultExecuting.
public class CustomOutputCache : OutputCacheAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
if(!(filterContext.Result is EmptyResult))
base.OnResultExecuting(filterContext);
}
}
I am trying to implement a global exception handling technique to avoid using try/catch blocks on every action of my controllers but my application crashes before the overridden OnException method or the ErrorHandleAttribute are reached.
Here is a simplified testing code:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Test()
{
throw new Exception("Exception Test");
}
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext == null || filterContext.ExceptionHandled)
{
return;
}
var message = filterContext.Exception.Message;
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
filterContext.ExceptionHandled = true;
}
}
and in Web.Config:
<system.web>
<customErrors mode="On" defaultRedirect="Error"/>
If I set a break point on the 'throw' line and try to access /Home/Test my application will crash and both OnException method and the HandleErrorAttribute will be reached only after that.
Am I missing something?
Thank you.
You need to register the HandleError filter.
filters.Add(new HandleErrorAttribute{View = "Error"});
I know attribute based routing works on action level but can I use same at controller level for following scenario?
I have a controller with name C1Controller but I want when url contains C1 or C2 or C3 then C1Controller to invoke. How to use Route attribute to achieve this?
Got answer from a post
"The most correct way would be to create a class that inherits ActionFilterAttribute and override OnActionExecuting method. This can then be registered in the GlobalFilters in Global.asax.cs"
Like:
public class InspectActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Check URL for c1, c2 ... and redirect if found
}
}
To use it, just add it to the global filters in global.asax:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new LogActionFilter());
}
Ref: Intercept all calls
ASP.NET MVC 4 intercept all incoming requests
Hope this helps!
Try This one
public class TheActionFilter: ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
if (controllerName !="C1" || controllerName !="C1" || controllerName !="C3")
return;
var redirectTarget = new RouteValueDictionary
{{"action", "ActionName"}, {"controller", "ControllerName"}};
filterContext.Result = new RedirectToRouteResult(redirectTarget);
filterContext = new RedirectResult(filterContext.HttpContext.Request.UrlReferrer.AbsolutePath) // The session you can get from the context like that:
var session = filterContext.HttpContext.Session;
}
}
In Your Controller
[TheActionFilter]
public class BookController : Controller
{
// Your Action Results
}
Sorry for the basic question.
From within the Global.asax, I want to get the absolute path to a controller's action, like we get by calling Response.Redirect("~/subfolder") from anywhere or by calling #Url.Content("~/controller/action") from within our views.
In my Global.asax events, I'd like to do something like this:
protected void Application_BeginRequest(object sender, EventArgs args)
{
if ( string.Compare(HttpContext.Current.Request.RawUrl, "~/foo", true) == 0 )
// do something
// I'd like the "~foo" to resolve to the virtual path relative to
// the application root
}
Here is the answer for your problem
You can simply get the controller and action name like this
protected void Application_BeginRequest(object sender, EventArgs args)
{
HttpContextBase currentContext = new HttpContextWrapper(HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
RouteData routeData = urlHelper.RouteCollection.GetRouteData(currentContext);
string action = routeData.Values["action"] as string;
string controller = routeData.Values["controller"] as string;
if (string.Compare(controller, "foo", true) == 0)
// do something
// if the controller for current request if foo
}
How to check the Session Timeout
void Session_Start(object sender, EventArgs e)
{
if (Session.IsNewSession && Session["SessionExpire"] == null)
{
//Your code
}
}
You have many options to do this. But I will not recommend to use Global.asax place to do such comparisons
Option - 1
This is also very important approach. You can use HttpModule.
Option - 2
Base Controller class
Option - 3
You can apply the Action Filter to an entire Controller class like below
namespace MvcApplication1.Controllers
{
[MyActionFilter]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
}
}
Whenever any of the actions exposed by the Home controller are invoked – either the Index() method or the About() method, the Action Filter class will execute first.
namespace MvcApplication1.ActionFilters
{
public class MyActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Your code for comparison
}
}
}
If you pay attention to the above code, the OnActionExecuting will execute before executing the Action Method
Option - 4
Using this approach will execute the OnActionExecuting for Index method only.
namespace MvcApplication1.Controllers
{
public class DataController : Controller
{
[MyActionFilter]
public string Index()
{
//Your code for comparison
}
}
}
How to get the current request DataTokens
RouteData.Values["controller"] //to get the current Controller Name
RouteData.Values["action"] //to get the current action Name
It´s better to create an ActionFilterAttribute and override OnActionExecuting method like this:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionDescriptor.ActionName == "Foo")
{
// do something
}
base.OnActionExecuting(filterContext);
}
Then you can apply the attribute on your BaseController, for example.
I need to do the following:
I have some Controllers ready and running, but now I want to create a BaseController.
Each of my Controllers should inherit from it like this:
public class MySecondController : BaseController
thats already running so far. Now the Problem:
I want to add a ViewBag into this base controller. This ViewBag should be accessable from every view which is called in my controllers.
How to realise this?
You can override OnActionExecuting method in the overridden method you can data to ViewBag dictionary.
public abstract class BaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
ViewBag.someThing = "someThing"; //Add whatever
base.OnActionExecuting(filterContext);
}
}
Updated for .net Core 2019:
using Microsoft.AspNetCore.Mvc.Filters;
public abstract class BaseController : Controller
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
ViewBag.someThing = "someThing"; //Add whatever
ViewData["someThingElse"] = "this works too";
TempData["anotherThing"] = "as does this";
base.OnActionExecuting(filterContext);
}
}