Asp.net MVC hijaxing returned view fix
-
28-10-2019 - |
Question
I am trying to use hijacking to do a single-page web application using mvc. The problem that I find is how to toggle the layout that the controller returns in an efficient way.
the most obvious non efficient solution would be to use this code on every controller:
if (Request.IsAjaxRequest())
{
return PartialView();
}
else
{
viewdata["controller"]= "x"; viewdata["action"]= "y";
return View("defaultview"); //I need view data because only one template main
//view is returned and based on the viewdata the main
//view loads the right partial view inside it
}
Is there a way to do the above code in a more simpler way? Maybe using a custom viewresult, which checks, if the request is AJAX, and returns the proper view. Or maybe some-sort of a base controller? I do not know how to implement both ideas so any guidance would be great.
Solution
One possibility is to write a custom action filter and subscribe to the OnActionExecuted
event. Inside you will check if the action was invoked using an AJAX request and if it returned a view result. In this case you will substitute this view result with a partial view result:
public class LayoutSelectorAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var result = filterContext.Result as ViewResult;
if (filterContext.HttpContext.Request.IsAjaxRequest() && result != null)
{
var partialViewResult = new PartialViewResult
{
ViewName = result.ViewName,
ViewData = result.ViewData,
TempData = result.TempData
};
filterContext.Result = partialViewResult;
}
}
}
Now you could decorate your controllers or actions with this attribute.
If you are using the Razor view engine another possibility is to tweak your _ViewStart.cshtml
file which is where the layout is defined:
@{
Layout = !ViewContext.HttpContext.Request.IsAjaxRequest()
? "~/Views/Shared/_Layout.cshtml"
: null;
}