C# – MVC 3: How to render a view without its layout page when loaded via ajax

asp.net-mvcasp.net-mvc-3cmaster-pagesrazor

I am learning about Progressive Enhancement and I have a question about AJAXifying views. In my MVC 3 project I have a layout page, a viewstart page, and two plain views.

The viewstart page is in the root of the Views folder and thus applies to all views. It specifies that all views should use _Layout.cshtml for their layout page. The layout page contains two navigation links, one for each view. The links use @Html.ActionLink() to render themselves to the page.

Now I have added jQuery and want to hijack these links and use Ajax to load their content on the page dynamically.

<script type="text/javascript">
    $(function () {
        $('#theLink').click(function () {
            $.ajax({
                url: $(this).attr('href'),
                type: "GET",
                success: function (response) {
                    $('#mainContent').html(response);
                }
            });
            return false;
        });
    });
</script>

There are two ways I can think of to do this, but I don't particularly like either one:

1) I can take the entire View's contents and place them in a partial view, then have the main view call the partial view when it is rendered. That way, using Request.IsAjaxRequest() in the controller, I can return View() or return PartialView() based on whether or not the request is an Ajax request. I can't return the regular view to the Ajax request because then it would use the layout page and I'd get a second copy of the layout page injected. However, I don't like this because it forces me to create empty views with just a @{Html.RenderPartial();} in them for the standard GET requests.

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return PartialView("partialView");
        else
            return View();
    }

Then in Index.cshtml do this:

@{Html.RenderPartial("partialView");}

2) I can remove the layout designation from _viewstart and specify it manually when the request is NOT Ajax:

    public ActionResult Index()
    {
        if (Request.IsAjaxRequest())
            return View(); // Return view with no master.
        else
            return View("Index", "_Layout"); // Return view with master.
    }

Does anyone have a better suggestion? Is there a way to return a view without its layout page? It would be much easier to explicitly say "don't include your layout" if it is an ajax request, than it would be to explicitly include the layout if it's not an ajax.

Best Answer

In ~/Views/ViewStart.cshtml:

@{
    Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}

and in the controller:

public ActionResult Index()
{
    return View();
}