PageRenderTime 55ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/Src/Commons.Web.Mvc/Attributes/AjaxControllerAttribute.cs

https://github.com/pworst/BoC
C# | 165 lines | 117 code | 12 blank | 36 comment | 48 complexity | 453f0333f447be48445083d0088e3d85 MD5 | raw file
  1. using System;
  2. using System.Linq;
  3. using System.Web.Mvc;
  4. using System.Web;
  5. using System.Web.Routing;
  6. using BoC.Web.Mvc.ActionResults;
  7. namespace BoC.Web.Mvc.Attributes
  8. {
  9. /// <summary>
  10. /// The AjaxControllerAttribute does a few things
  11. /// - if the current request is a json-request, it returns the model as a json result
  12. /// - if the current request is an xml-request, it returns the model as an xml result
  13. /// - if the current request is an ajax-request, it returns a partialviewresult
  14. /// If your controller uses this attribute, you can always return a normal ViewResult, it will be transformed by this actionfilter
  15. /// </summary>
  16. public class AjaxControllerAttribute: ActionFilterAttribute
  17. {
  18. public override void OnActionExecuted(ActionExecutedContext filterContext)
  19. {
  20. base.OnActionExecuted(filterContext);
  21. var responseType = filterContext.HttpContext.Request.GetPreferedResponseType();
  22. if (filterContext.HttpContext.Request.IsJqAjaxRequest()
  23. && filterContext.Exception == null
  24. && ((filterContext.Result is RedirectToRouteResult) || filterContext.Result is RedirectResult))
  25. {
  26. //If we have redirect result, and it is an ajax request:
  27. // - IF it is json or xml:
  28. // we'll return 200 OK with the URL in the header, the user can decide if he wants to redirect
  29. // - if it is an html request, we'll redirect to the new action but send info about the ajax-request with it
  30. var redir = filterContext.Result as RedirectToRouteResult;
  31. if (responseType == ResponseType.Json || responseType == ResponseType.Xml) //we'll return a redirect object
  32. {
  33. string url;
  34. if (redir != null)
  35. {
  36. url = UrlHelper.GenerateUrl(
  37. redir.RouteName,
  38. null /* actionName */,
  39. null /* controllerName */,
  40. redir.RouteValues,
  41. RouteTable.Routes,
  42. filterContext.RequestContext,
  43. false /* includeImplicitMvcValues */);
  44. }
  45. else
  46. {
  47. url = ((RedirectResult) filterContext.Result).Url;
  48. }
  49. filterContext.RequestContext.HttpContext.Response.AddHeader("Location", url);
  50. }
  51. else if (redir != null && !redir.RouteValues.ContainsKey("__mvcajax")) //without these extra params we can't detect an ajax request in FireFox :(
  52. {
  53. redir.RouteValues["__mvcajax"] = "true";
  54. redir.RouteValues["resultformat"] = filterContext.RouteData.Values["resultformat"] ??
  55. filterContext.RouteData.DataTokens["resultformat"];
  56. redir.RouteValues["format"] = filterContext.RouteData.Values["format"];
  57. return;
  58. }
  59. }
  60. if (filterContext.IsChildAction || filterContext.HttpContext.Request.IsJqAjaxRequest())
  61. {
  62. var result = filterContext.Result as ViewResult;
  63. if (result != null && responseType == ResponseType.Html)
  64. {
  65. var viewResult = filterContext.Result as ViewResult;
  66. //prefer partial
  67. if (viewResult != null)
  68. {
  69. filterContext.Result = new PartialViewResult()
  70. {
  71. TempData = viewResult.TempData,
  72. ViewData = viewResult.ViewData,
  73. ViewName = viewResult.ViewName,
  74. };
  75. }
  76. }
  77. else if (responseType == ResponseType.Json || responseType == ResponseType.Xml)
  78. {
  79. ViewDataDictionary data = filterContext.Result is ViewResultBase ? ((ViewResultBase)filterContext.Result).ViewData : filterContext.Controller.ViewData;
  80. object model = data;
  81. if (filterContext.Exception != null)
  82. model = filterContext.Exception;
  83. else if (data != null && data.Model != null)
  84. model = data.Model;
  85. if (model is Exception)
  86. {
  87. filterContext.Result = null;
  88. Exception exc = ((Exception)model).InnerException ?? ((Exception)model);
  89. if (exc is HttpException)
  90. {
  91. filterContext.HttpContext.Response.StatusCode = ((HttpException)exc).GetHttpCode();
  92. }
  93. else
  94. {
  95. filterContext.HttpContext.Response.StatusCode = 500;
  96. }
  97. filterContext.HttpContext.Response.StatusDescription = exc.Message;
  98. filterContext.ExceptionHandled = true;
  99. model = new SimpleException(exc);
  100. }
  101. if (responseType == ResponseType.Json)
  102. {
  103. //see if custom JsonRequestBehavior has been set
  104. var attrib = filterContext.ActionDescriptor.GetCustomAttributes(typeof (JsonRequestBehaviorAttribute), true).OfType<JsonRequestBehaviorAttribute>().FirstOrDefault();
  105. if (attrib == null)
  106. {
  107. attrib = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (JsonRequestBehaviorAttribute), true).OfType<JsonRequestBehaviorAttribute>().FirstOrDefault();
  108. }
  109. if (!(filterContext.Result is JsonResult))
  110. {
  111. filterContext.Result = new JsonResult()
  112. {
  113. Data = model ?? new object(),
  114. JsonRequestBehavior = (attrib == null) ? JsonRequestBehavior.DenyGet : attrib.JsonRequestBehavior
  115. };
  116. }
  117. else if (attrib != null)
  118. {
  119. (filterContext.Result as JsonResult).JsonRequestBehavior = attrib.JsonRequestBehavior;
  120. }
  121. }
  122. else if (!(filterContext.Result is XmlResult))
  123. {
  124. filterContext.Result = new XmlResult(model);
  125. }
  126. }
  127. }
  128. }
  129. /* In asp.net mvc 2, the OnActionExecuted seems to be triggered always, so we don't need this seperate function anymore
  130. void IExceptionFilter.OnException(ExceptionContext filterContext)
  131. {
  132. if (filterContext.Result == null && filterContext.HttpContext.Request.GetPreferedResponseType() == ResponseType.Json)
  133. {
  134. filterContext.Result = new JsonResult()
  135. {
  136. Data = new {errors = new SimpleException[] {new SimpleException(filterContext.Exception)}}
  137. };
  138. filterContext.HttpContext.Response.Clear();
  139. filterContext.ExceptionHandled = true;
  140. if (filterContext.Exception is HttpException)
  141. {
  142. filterContext.HttpContext.Response.StatusCode = ((HttpException)filterContext.Exception).GetHttpCode();
  143. }
  144. else
  145. {
  146. filterContext.HttpContext.Response.StatusCode = 500;
  147. }
  148. filterContext.HttpContext.Response.StatusDescription = filterContext.Exception.Message;
  149. }
  150. }
  151. */
  152. }
  153. }