Pages

Advertisement

Wednesday, August 19, 2009

Fun with Http Headers in ASP.NET MVC Action Filters - Kazi Manzur Rashid's Blog

Do you want your ASP.NET MVC application to auto redirect to a specific url after a certain interval, yes you can use javascript window.location, what about without javascript? Check this codes:
view source
print?
01.[AutoRefresh(ControllerName = "Home", ActionName = "About", DurationInSeconds = 10)]
02.public ActionResult Index1()
03.
04.[AutoRefresh(ActionName = "About", DurationInSeconds = 15)]
05.public ActionResult Index2()
06.
07.[AutoRefresh(RouteName = "ByFavoriteRoute", DurationInSeconds = 30)]
08.public ActionResult Index3()
09.
10.[AutoRefresh(DurationInSeconds = 45)]
11.public ActionResult Index4()

If the browsers is idle for the specified period, it will automatically redirect to that Action. if you do not specify any action/controller/route (Index4) it will auto refresh the current url. How? Well I am just using/abusing some http header, check it out:
view source
print?
01.[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
02.[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
03.public class AutoRefreshAttribute : ActionFilterAttribute
04.{
05. public const int DefaultDurationInSeconds = 300; // 5 Minutes
06.
07. public AutoRefreshAttribute()
08. {
09. DurationInSeconds = DefaultDurationInSeconds;
10. }
11.
12. public int DurationInSeconds
13. {
14. get;
15. set;
16. }
17.
18. public string RouteName
19. {
20. get;
21. set;
22. }
23.
24. public string ControllerName
25. {
26. get;
27. set;
28. }
29.
30. public string ActionName
31. {
32. get;
33. set;
34. }
35.
36. public override void OnResultExecuted(ResultExecutedContext filterContext)
37. {
38. string url = BuildUrl(filterContext);
39. string headerValue = string.Concat(DurationInSeconds, ";Url=", url);
40.
41. filterContext.HttpContext.Response.AppendHeader("Refresh", headerValue);
42.
43. base.OnResultExecuted(filterContext);
44. }
45.
46. private string BuildUrl(ControllerContext filterContext)
47. {
48. UrlHelper urlHelper = new UrlHelper(filterContext.RequestContext);
49. string url;
50.
51. if (!string.IsNullOrEmpty(RouteName))
52. {
53. url = urlHelper.RouteUrl(RouteName);
54. }
55. else if (!string.IsNullOrEmpty(ControllerName) && !string.IsNullOrEmpty(ActionName))
56. {
57. url = urlHelper.Action(ActionName, ControllerName);
58. }
59. else if (!string.IsNullOrEmpty(ActionName))
60. {
61. url = urlHelper.Action(ActionName);
62. }
63. else
64. {
65. url = filterContext.HttpContext.Request.RawUrl;
66. }
67.
68. return url;
69. }
70.}

Can’t think any proper usage of this action filter, may be you can use it for any iframe kind of page where you want to show some live statistics. Okay now let’s try one more time to abuse this Refresh header, this time it is a very common scenario.

You want your secured (marked as Authorized) actions to automatically redirect to login page when the session expires. Now try this:
view source
print?
01.[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
02.[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
03.public class AutoRedirectToLogin : ActionFilterAttribute
04.{
05. public override void OnResultExecuted(ResultExecutedContext filterContext)
06. {
07. string url = FormsAuthentication.LoginUrl;
08. int durationInSeconds = ((filterContext.HttpContext.Session.Timeout * 60) + 10); // Extra 10 seconds
09.
10. string headerValue = string.Concat(durationInSeconds, ";Url=", url);
11.
12. filterContext.HttpContext.Response.AppendHeader("Refresh", headerValue);
13.
14. base.OnResultExecuted(filterContext);
15. }
16.}

When the session expires it will automatically redirect to the login page without requiring the extra click from the user.

Word of Caution: Do not use the Refresh meta header if you want your url to include in the search engine index (verified in Google, not sure about the others). For example, your Page A wants to auto redirect to Page B, the Page A only has this header, in that case Page A will not be indexed.