Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC nested views and partial views

I am in the process of creating a prototype project using MVC 3 and I have come across a situation which I can't seem to find an answer for and it seems like I might be approaching the problem the wrong way.

A quick overview of my project; it is based on the MVC template you get with Visual Studio and I use the links (tabs) on the supplied _Layout view to access some of my other views. One of these links opens a second partial view that again contains links for more views (admin specific. hence the split). The problem I am having is that I can't seem to display views with the @RenderBody in the second partial view, which I understand is because you can't have more than one @RenderBody in a completed HTML file, which makes sense.

So my question is, how can I display the views in this manner? Also, probably more importantly, is this the correct way to achieve this 'sub menu' system I am trying for or is there a better way to achieve this?

Here is the relevant parts of the views, first is the 'main' _Layout file:

<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>Test App</h1>
            </div>
            <nav>
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    @if (User.Identity.IsAuthenticated)
                    {
                        <li>@Html.ActionLink("Contracts", "List", "Contract", new { user=User.Identity.Name, page=1 }, null)</li>
                    }
                    @if (User.IsInRole("Administrator"))
                    {
                        <li id="admin">@Html.ActionLink("Administration", "Administration", "Home")</li>
                    }
                </ul>
            </nav>
        </header>
        <section id="main">
            @RenderBody()
        </section>
        <footer>
        </footer>
    </div>
</body>

When clicking the <li id="admin">@Html.ActionLink("Administration", "Administration", "Home")</li> link, then the Home controller return the second partial view shown below:

<header>
    <div id="admintitle">
        <h1>Administration</h1>
    </div>  
</header>
<body>
    <div id="div-1a">
         <nav>
            <ul id="adminmenu">
                <li>@Html.ActionLink("Contact", "List", "Contact")</li>
                <li>@Html.ActionLink("Home", "Index", "Home")</li>
            </ul>
        </nav>
    </div>
    <div id="div-1c">
        <h1>Test</h1>   
    </div>
    <section id="adminmain">
        @RenderBody()
    </section>
</body>

When I try and run the code, it fails due to the second @RenderBody, which is understandable.

If you need any more information, then please let me know.

Thanks very much.

like image 322
XN16 Avatar asked Jun 21 '26 05:06

XN16


2 Answers

You can not use @RenderBody() multiple times. One @RenderBody() in your main _Layout file is fair enough. In your second view use instead @RenderPartial() or @RenderAction.

UPDATE (based on first comment)

Let's say you want to render /Administrator/TheAction, so you will call

@{
    Html.RenderAction("TheAction", "Administrator");
}

TheAction action will look like this:

public PartialViewResult TheAction() {
    return PartialView();
}

And it will render the view in ~/Views/Administrator/TheAction.cshtml right inside the place from which you called the RenderAction().

The importance is that it does not accomplish another @RenderBody. As you can see in TheAction() example, you are returning PartialViewResult, which does not have any @RenderBody() helper.

like image 157
Roman Mazur Avatar answered Jun 23 '26 20:06

Roman Mazur


Convert

From

<section id="adminmain">
   @RenderBody()
</section>

To

   <div id="adminmain"></div>

From

@Html.ActionLink("Contact", "List", "Contact")

To

@Ajax.ActionLink("Contact", "List", "Contact", new AjaxOptions { UpdateTargetId = "adminmain" })

And in ContactController List action return PartialView() instead of 'View()'.

Do not forget to include jquery.unobtrusive-ajax in your view to make Ajax work.

And before all read Roman's Answer

like image 34
Mohayemin Avatar answered Jun 23 '26 19:06

Mohayemin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!