dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.15k stars 9.92k forks source link

Why we need layouts if we have partials? #10430

Closed elgunhuseynli closed 4 years ago

elgunhuseynli commented 5 years ago

Layout and partial mechanism of Razor is very difficult to understand. As far as I can understand, layout is seems like reverse of the partial. For example, in the below we put @ViewData["Title"] before the @RenderBody. But value of the Title is set inside body.

_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>@ViewData["Title"] - Askify</title>
</head>
<body>
    @RenderBody()
</body>

And here is the Index.cshtml.

Index.cshtml

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
</div>

How is that possible to use Title before it's value set? Is order of code reversed? I mean, is RenderBody() called before rendering layout?

Also, can we use partials to do same thing? Like this:

Index.cshtml

@{
    ViewData["Title"] = "Home Page";
}

<!DOCTYPE html>
<html>
    <partial name="_Header" />
    <body>
        <h1>Hello world</h1>
    </body>
</html>
_Header.cshtml

<head>
    <title>@ViewData["Title"] - Askify</title>
</head>

If yes, then why need layouts. Isn't it better to use only one technique?

mysteryx93 commented 5 years ago

Layout and Partial serve completely different purpose. Layout contains shared layout code "around" a page, while Partials contain shared code "within" the content.

Note that the @page (or @view) attribute is on the page itself, not on the layout. Thus the page gets executed first, then it find the Layout property and calls the layout and by that time the Title is already set.

If you didn't have layout, you'd have to repeat the html, head and body tags in every page, and putting them on partials you'd insert on every page perhaps could be done but would be very dirty.

EdiWang commented 5 years ago

In ancient time, when we were using ASP (not even .NET was invented), there was no layout page. We usually do it by using server side Include like , very much like what you suggested for partials. Then, ASP.NET WebForms came up, with a notion of "MasterPage", which evolved to Layout page in MVC.

The purpose of Layout over partial I can think of is:

  1. When you have open HTML tags and close HTML tags like this:

    <section>
    <div>
    @RenderBody()
    </div>
    </section>

    Layout can handle it well. But if you use partial, you have to define two partials to wrap your body: Partial1:

    <section>
    <div>

    Partial2:

    </div>
    </section>

    Which makes it difficult to maintain code readability.

  2. Partials can have inheritance, just like WebForms' MasterPage. This is especially useful when wrapping different skins in a product.

elgunhuseynli commented 5 years ago

Layout can handle it well. But if you use partial, you have to define two partials to wrap your body:

I think this problem can be solved with the help of delegates.

elgunhuseynli commented 5 years ago

For example, in MarkoJS, this problem is solved with injecting body to partials. It can easily be done in C# with delegates. Please take a look at here:

https://markojs.com/docs/body-content/

And here is the pseudo-code

app.cshtml

<html lang="en">
    <head>
        <title>@title</title>
    </head>
    <body>
        @body()
    </body>
</html>
about.cshtml

<app title="About">
    <h1>About Us</h1>
    <p>Lorem ipsum dolor sid amed</p>
</app>
ghost commented 4 years ago

Thank you for contacting us. Due to no activity on this issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.