ASP.NET MVC 3: Layouts and Sections with Razor

This is another in a series of posts I’m doing that cover some of the new ASP.NET MVC 3 features:

In today’s post I’m going to go into more details about how Layout pages work with Razor.  In particular, I’m going to cover how you can have multiple, non-contiguous, replaceable “sections” within a layout file – and enable views based on layouts to optionally “fill in” these different sections at runtime.  The Razor syntax for doing this is clean and concise.

I’ll also show how you can dynamically check at runtime whether a particular layout section has been defined, and how you can provide alternate content (or even an alternate layout) in the event that a section isn’t specified within a view template.  This provides a powerful and easy way to customize the UI of your site and make it clean and DRY from an implementation perspective.

What are Layouts?

You typically want to maintain a consistent look and feel across all of the pages within your web-site/application.  ASP.NET 2.0 introduced the concept of “master pages” which helps enable this when using .aspx based pages or templates.  Razor also supports this concept with a feature called “layouts” – which allow you to define a common site template, and then inherit its look and feel across all the views/pages on your site.

I previously discussed the basics of how layout files work with Razor in my ASP.NET MVC 3: Layouts with Razor blog post.  Today’s post will go deeper and discuss how you can define multiple, non-contiguous, replaceable regions within a layout file that you can then optionally “fill in” at runtime.

Site Layout Scenario

Let’s look at how we can implement a common site layout scenario with ASP.NET MVC 3 and Razor.  Specifically, we’ll implement some site UI where we have a common header and footer on all of our pages.  We’ll also add a “sidebar” section to the right of our common site layout. 

On some pages we’ll customize the SideBar to contain content specific to the page it is included on:

image

And on other pages (that do not have custom sidebar content) we will fall back and provide some “default content” to the sidebar:

image

We’ll use ASP.NET MVC 3 and Razor to enable this customization in a nice, clean way. 

Below are some step-by-step tutorial instructions on how to build the above site with ASP.NET MVC 3 and Razor.

Part 1: Create a New Project with a Layout for the “Body” section

We’ll begin by using the “File->New Project” menu command within Visual Studio to create a new ASP.NET MVC 3 Project.  We’ll create the new project using the “Empty” template option:

image

This will create a new project that has no default controllers in it:

image

Creating a HomeController

We will then right-click on the “Controllers” folder of our newly created project and choose the “Add->Controller” context menu command.  This will bring up the “Add Controller” dialog:

image

We’ll name the new controller we create “HomeController”.  When we click the “Add” button Visual Studio will add a HomeController class to our project with a default “Index” action method that returns a view:

image

We won’t need to write any Controller logic to implement this sample – so we’ll leave the default code as-is. 

Creating a View Template

Our next step will be to implement the view template associated with the HomeController’s Index action method.  To implement the view template, we will right-click within the “HomeController.Index()” method and select the “Add View” command to create a view template for our home page:

image

This will bring up the “Add View” dialog within Visual Studio. 

image

We do not need to change any of the default settings within the above dialog (the name of the template was auto-populated to Index because we invoked the “Add View” context menu command within the Index method). 

When we click the “Add” Button within the dialog, a Razor-based “Index.cshtml” view template will be added to the \Views\Home\ folder within our project.  Let’s add some simple default static content to it:

image

Notice above how we don’t have an <html> or <body> section defined within our view template.  This is because we are going to rely on a layout template to supply these elements and use it to define the common site layout and structure for our site (ensuring that it is consistent across all pages and URLs within the site). 

Customizing our Layout File

Let’s open and customize the default “_Layout.cshtml” file that was automatically added to the \Views\Shared folder when we created our new project:

image

The default layout file (shown above) is pretty basic and simply outputs a title (if specified in either the Controller or the View template) and adds links to a stylesheet and jQuery.  The call to “RenderBody()” indicates where the main body content of our Index.cshtml file will merged into the output sent back to the browser.

Let’s modify the Layout template to add a common header, footer and sidebar to the site:

image

We’ll then edit the “Site.css” file within the \Content folder of our project and add 4 CSS rules to it:

image

And now when we run the project and browse to the home “/” URL of our project we’ll see a page like below:

image

Notice how the content of the HomeController’s Index view template and the site’s Shared Layout template have been merged together into a single HTML response. 

Below is what the HTML sent back from the server looks like:

image

Part 2: Adding a “SideBar” Section

Our site so far has a layout template that has only one “section” in it – what we call the main “body” section of the response. 

Razor also supports the ability to add additional "named sections” to layout templates as well.  These sections can be defined anywhere in the layout file (including within the <head> section of the HTML), and allow you to output dynamic content to multiple, non-contiguous, regions of the final response.

Defining the “SideBar” section in our Layout

Let’s update our Layout template to define an additional “SideBar” section of content that will be rendered within the <div id=”sidebar”> region of our HTML.  We can do this by calling the RenderSection(string sectionName, bool required) helper method within our Layout.cshtml file like below:

  image

The first parameter to the “RenderSection()” helper method specifies the name of the section we want to render at that location in the layout template.  The second parameter is optional, and allows us to define whether the section we are rendering is required or not.  If a section is “required”, then Razor will throw an error at runtime if that section is not implemented within a view template that is based on the layout file (which can make it easier to track down content errors).  If a section is not required, then its presence within a view template is optional, and the above RenderSection() code will render nothing at runtime if it isn’t defined.

Now that we’ve made the above change to our layout file, let’s hit refresh in our browser and see what our Home page now looks like:

image

Notice how we currently have no content within our SideBar <div> – that is because the Index.cshtml view template doesn’t implement our new “SideBar” section yet.

Implementing the “SideBar” Section in our View Template

Let’s change our home-page so that it has a SideBar section that outputs some custom content.  We can do that by opening up the Index.cshtml view template, and by adding a new “SiderBar” section to it.  We’ll do this using Razor’s @section SectionName { } syntax:

image

We could have put our SideBar @section declaration anywhere within the view template.  I think it looks cleaner when defined at the top or bottom of the file – but that is simply personal preference. 

You can include any content or code you want within @section declarations.  Notice above how I have a C# code nugget that outputs the current time at the bottom of the SideBar section.  I could have also written code that used ASP.NET MVC’s HTML/AJAX helper methods and/or accessed any strongly-typed model objects passed to the Index.cshtml view template.

Now that we’ve made the above template changes, when we hit refresh in our browser again we’ll see that our SideBar content – that is specific to the Home Page of our site – is now included in the page response sent back from the server:

image

The SideBar section content has been merged into the proper location of the HTML response :

image

Part 3: Conditionally Detecting if a Layout Section Has Been Implemented

Razor provides the ability for you to conditionally check (from within a layout file) whether a section has been defined within a view template, and enables you to output an alternative response in the event that the section has not been defined.  This provides a convenient way to specify default UI for optional layout sections. 

Let’s modify our Layout file to take advantage of this capability.  Below we are conditionally checking whether the “SideBar” section has been defined without the view template being rendered (using the IsSectionDefined() method), and if so we render the section.  If the section has not been defined, then we now instead render some default content for the SideBar: 

image

Note: You want to make sure you prefix calls to the RenderSection() helper method with a @ character – which will tell Razor to execute the HelperResult it returns and merge in the section content in the appropriate place of the output.  Notice how we wrote @RenderSection(“SideBar”) above instead of just RenderSection(“SideBar”).  Otherwise you’ll get an error.

Above we are simply rendering an inline static string (<p>Default SideBar Content</p>) if the section is not defined.  A real-world site would more likely refactor this default content to be stored within a separate partial template (which we’d render using the Html.RenderPartial() helper method within the else block) or alternatively use the Html.Action() helper method within the else block to encapsulate both the logic and rendering of the default sidebar.

When we hit refresh on our home-page, we will still see the same custom SideBar content we had before.  This is because we implemented the SideBar section within our Index.cshtml view template (and so our Layout rendered it):

image

Let’s now implement a “/Home/About” URL for our site by adding a new “About” action method to our HomeController:

image

The About() action method above simply renders a view back to the client when invoked.  We can implement the corresponding view template for this action by right-clicking within the “About()” method and using the “Add View” menu command (like before) to create a new About.cshtml view template. 

We’ll implement the About.cshtml view template like below. Notice that we are not defining a “SideBar” section within it:

image

When we browse the /Home/About URL we’ll see the content we supplied above in the main body section of our response, and the default SideBar content will rendered:

image

The layout file determined at runtime that a custom SideBar section wasn’t present in the About.cshtml view template, and instead rendered the default sidebar content.

One Last Tweak…

Let’s suppose that at a later point we decide that instead of rendering default side-bar content, we just want to hide the side-bar entirely from pages that don’t have any custom sidebar content defined.  We could implement this change simply by making a small modification to our layout so that the sidebar content (and its surrounding HTML chrome) is only rendered if the SideBar section is defined.  The code to do this is below:

image

Razor is flexible enough so that we can make changes like this and not have to modify any of our view templates (nor make change any Controller logic changes) to accommodate this.  We can instead make just this one modification to our Layout file and the rest happens cleanly.  This type of flexibility makes Razor incredibly powerful and productive.

Summary

Razor’s layout capability enables you to define a common site template, and then inherit its look and feel across all the views/pages on your site.

Razor enables you to define multiple, non-contiguous, “sections” within layout templates that can be “filled-in” by view templates.  The @section {} syntax for doing this is clean and concise.  Razor also supports the ability to dynamically check at runtime whether a particular section has been defined, and to provide alternate content (or even an alternate layout) in the event that it isn’t specified.  This provides a powerful and easy way to customize the UI of your site - and make it clean and DRY from an implementation perspective.

Hope this helps,

Scott

P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu

Published Thursday, December 30, 2010 12:27 AM by ScottGu
Filed under: , ,

Comments

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 3:40 AM by Jalpesh Vadgama

Hi Scott,

Very well written post Great Job!!!. You are guys are doing superb Job with ASP.NET MVC Razor.Can you please some thing about entity framework 5.0 CTP.

Best Regards,

Jalpesh

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 3:56 AM by shiju

Very nice post. ASP.NET MVC 3, Razor and EF Code-First are the great combination for building great web apps.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 4:39 AM by Ghasem Karimi

Hi Scott,Very well written post Great Job!

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 4:49 AM by phutang

Razor is nice syntax, very clarified. I am waiting MVC 3 RTM in middle jan with new features ^.^

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 5:35 AM by herzmeister der welten

So when can we have something like Razor for XAML in Silverlight and WPF? We're kinda tired of all that DataTemplate and Text="{Binding Path=Stuff.KillMePls BindingMode=ThousandFold RelativeSource={RelativeSource={RelativeSource={RelativeSource FindAncestorOfThisCivilization AncestorType=NotMyType Level=42}}}}}}}}}}}}}" nonsense.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 6:14 AM by BatsIhor

Very nice and easy explanation thanks! I think you need to add another one post about EF CF it will be very helpful.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 7:26 AM by Fasih Hansmukh

Nice, i like that.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 7:28 AM by Zain Shaikh

I'm lovin' Razor :D

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 7:29 AM by Khushal Patel

Hey Scott, Nice post can you tell us how to modify razor default templates

thanks

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 8:34 AM by Trey

Razor should be said twice when spoken and only in your best battle droid voice.

Great post from another great Scott (Guthrie, Hanselman, Mitchell)!

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 8:40 AM by qanuj

Very Nice .. I just needed the method name for IsSectionDefined. that does the whole trick. I already use this to do nested layout pages.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 8:58 AM by tobi

looks like a great cms for developers with that nice composability support.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 10:18 AM by Craig Quillen

How do you do nested layouts?  And how do they interact with sections?  Does Razor's sections have an append model like spark, or a total replace model like masterpages?

The spark view engine uses an append/cumulative model for adding content to sections.  This allows the nested layouts and the content page can add content to a single section without having to resort to defining new section identifiers at each layer.

You can still define nested sections with different ids if you want of course, but the append model does make certain use cases much nicer.  

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 10:42 AM by Danny

Nice post Scott.

I've tried implementing a section in a nested view but it doesn't work.

It seems that the section has to be implemented in the page that uses the layout.

Is there a reason that a partial view a couple of levels down can't implement a section?

Thanks again.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 11:14 AM by Colin Farr

Scott,

Sounds very much like master pages. What are the benefits of "layouts" over master pages or can't you use master pages in the razor engine and this is a replacement?

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 11:29 AM by Tim Cartwright

Scott awesome stuff. Question though. If you wanted to use another cshtml file for the section would that be possible? For example say you had several different defaults that you wanted to use on different sets of pages. Would that be possible?

Sorry if it is a stupid question, not very familiar with Razor.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 11:49 AM by Tim Cartwright

Scott, never mind. I RTFM'ed some of your earlier posts and discovered html helpers. AWESOME. Reading more.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 12:01 PM by Tim Cartwright

Ok, I read through all of your posts, and I do have a question that is not answered in any of them. How do you do localization with Razor?

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 3:35 PM by ScottGu

@Jalpesh,

>>>>>>> Can you please some thing about entity framework 5.0 CTP.

Morteza has a great series of EF Code First posts going.  Check them out (and subscribe to his RSS feed) here: http://weblogs.asp.net/manavi/

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 3:36 PM by ScottGu

@Khushal,

>>>>>>> Hey Scott, Nice post can you tell us how to modify razor default templates

Can you provide more details on what you are looking for? I'm not sure I understand.

Thanks,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 3:51 PM by ScottGu

@Craig,

>>>>>> How do you do nested layouts?  And how do they interact with sections?  Does Razor's sections have an append model like spark, or a total replace model like masterpages?  The spark view engine uses an append/cumulative model for adding content to sections.  This allows the nested layouts and the content page can add content to a single section without having to resort to defining new section identifiers at each layer.  You can still define nested sections with different ids if you want of course, but the append model does make certain use cases much nicer.  

I'm planning to do my next blog post in this series on nested layouts.  Razor allows you to override the sections of your immediate parent layout, and then optionally add new sections that can be overriden in a sub-layout/view.  I need to read up on Spark's append model - I think that is slightly different than what Razor does today.

Marcin has a blog post that talks about nested layouts (and how to redefine sections in them): blogs.msdn.com/.../Razor-Nested-Layouts-and-Redefined-Sections.aspx

Stay tuned for my blog post on the subject.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 5:08 PM by ScottGu

@Danny,

>>>>>>> I've tried implementing a section in a nested view but it doesn't work. It seems that the section has to be implemented in the page that uses the layout.  Is there a reason that a partial view a couple of levels down can't implement a section?

My next post in this series is going to cover how to implement nested layouts.  Marcin has a post on this topic that you can also look at in the meantime: blogs.msdn.com/.../razor-nested-layouts-and-redefined-sections.aspx

Hope this helps!

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 5:11 PM by ScottGu

@Colin,

>>>>>>> Sounds very much like master pages. What are the benefits of "layouts" over master pages or can't you use master pages in the razor engine and this is a replacement?

Conceptually layouts are very much like master pages.  Note that you can use master pages and .aspx view templates with ASP.NET MVC.  That was the only built-in template syntax option with ASP.NET MVC 1 and 2 - and continues to be fully supported with ASP.NET MVC 3.

This blog post of mine talks a little about why we introduced Razor as an option: weblogs.asp.net/.../introducing-razor.aspx Layouts follow the same philosophy that we used with the rest of Razor - which has been to try and keep the syntax concise and fluid as much as possible, and to try and remove as much "syntax noise" as possible from the markup.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 5:13 PM by ScottGu

@Tim,

>>>>>>>> Ok, I read through all of your posts, and I do have a question that is not answered in any of them. How do you do localization with Razor?

Generally we recommend using the resource model that is built-into ASP.NET to handle localization with Razor. Because you use standard VB and C# code within Razor templates, you get access to all of the standard localization/resource APIs available with .NET.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, December 30, 2010 10:20 PM by Siamak

Great Post!  Now just waiting for the final bits of MVC 3 and ADO.NET EF CodeFirst.  

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 3:27 AM by Andrea Bioli

How can I handle this scenario?

I create a '_box' partial view (with a required section):

<div class="_box">

   <div class="title">

       <span>News</span>

   </div>

   <div>

       @RenderSection("Content", required: true)

   </div>

</div>

With CSS I can obviously create the real style.

Now I would like to use it dynamically (and many times on the same page) with custom content: I think the most flexible way would be with

@Html.Partial("_box")

but I lack the way to give it the content, maybe in the form of another partial page! This would be the best way to style dynamic content!

Thanks in advance

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 6:20 AM by akachai

Scott,

One question on render section, It it possible to do it more declarative way like

@RenderSection("SideBar")  {

<p> Default SideBar Content ... </p>

}

I think doing this way is more easily to implement when you got more content on side bar, it is the same way that webform view engine implement on asp:content and asp:contentplaceholder which is no need to use if statement.

Thanks

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 7:34 AM by Mohamed Meligy

This is very nice. Razor is developing from yet-another-ViewEngine to a really nice one in general, and I love it!

One small comment, the use of IsSectionDefined() to add default content is too verbose compared to, for example, the way you do default content in ContentPlaceHolder in webforms MasterPages. I think it needs a better syntax.

One possible proposal (not 100% sure about it), is making RenderSection a boolean instead of (assumed) Void. RenderSection() can check IsSectionDefined(), return its value, and render only if the value is true.

It isn't SoC for sure and makes some non-obvious behavior (that's why I'm not sure about it), but then we can write:

@if( ! RenderSection("SideBar") {

   <p>Default SideBar content...</p>

}

.

Also, is the tooling aware somehow of all sections defined in a layout? Can it generate sections when creating a View based on the sections defined in the layout (reflecting on ContentPlaceHolders and MasterPages again)? I assume this might be harder to tell from the layout but it'll be nice if it can be obtained and even have intellisense for it. If it's not possible, I'll hope in extensions like Resharper or T4MVC to do it.

Thanks a lot.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 7:38 AM by Mohamed Meligy

@Andrea Bioli

Given you'll use a Partial, I think you can make anything that is dynamic in the Partial View be a part of the typed Model associated with this Partial. You can call Partials from Partials (I assume the same for Sections) and the name of the Partial / Section can be simply a Model property.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 8:08 AM by szkolenia bhp

nice article, good job:)

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 1:01 PM by Andrea Bioli

@Mohamed

First of all, thanks for your interest: reading what you wrote made me feel silly, because I missed a right point!

(But) things became interesting when I tried to implement this strategy...

So, just with the above example, I made a BoxModel class with just a string property (Content), and tried to execute the following code:

@Html.Partial("_box", new BoxModel { Content = "_NewsContent" })

where of course _NewsContent is another partial page.

What I get is a really strange error, without explanation of any possible solution:

Server Error in '/' Application.

The file "~/Views/Shared/_box.cshtml" cannot be requested directly because it calls the "RenderSection" method.

So it looks like I am not entitle to make such a composite call...

I already managed the problem writing some other partial page like this one:

@{

   Layout = "~/Views/Shared/_box.cshtml";

}

@section Content

{

   Ciao

}

It's a good solution, but requires one page for every possible use of the partial 'box', hence not flexible like the first idea...

Funny and interesting problem, isn'it?

:-)

Thanks again

Andrea

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Friday, December 31, 2010 10:57 PM by Mohamed Meligy

@Andrea

Yeah, your problem is what is solved by ITemplate or template controls in webforms. The controls composition model is the best part of webforms, not yet to see a near-powerful composition model for ASP.NET MVC.

One thing that can help this if implemented in ASP.NET MVC is being able to pass a block of text/code to Razor statement. You can already do:

if (...) {

  <p> Some markup and @"code" here

}

It'll be great if you can do something like:

@someProperty = {

  <p> Some markup and @"code" here</p>

}

or even:

@{someVariable = }

  <p> Some markup and @"code" here</p>

@{;}

It's not as easy as it sounds as <p> Some markup and @"code" here</p> in Razor is now directly sent to internal method "WriteLiteral()", and I bet this is everywhere in Razor (even the "if" part), so, it might be hard to change that to simply return the value to the calling context instead.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Saturday, January 1, 2011 7:11 AM by Andrea Bioli

@Mohamed

Yes, it's possible to do what you say, but it's not the most flexible and readable solution, it's really a shame we cannot do it that way in MVC.

What I cannot still understand is why I get that error, what it means and what it's current limitation in MVC that makes that impossible.

Anyway, thank you very very much for your time and for sharing your thoughts!

Andrea Bioli

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Saturday, January 1, 2011 2:10 PM by rickj1

Great stuff merry Xmas and a happy new year to you and the Microsoft team

thanks for all your hard work at making dreams come true

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Saturday, January 1, 2011 2:23 PM by Martin Wawrusch

Quick question for you Scott:

I want to change from razor view engine to another view engine (markdown in my case) within a razor view. Is that possible, and if so how?

Thanks

Martin

PS: It would be really great for the next release of asp.net mvc if you would support sass and a system like compass for css and javascript. It's a shame that we are still creating css like it's 1996 on Microsoft platforms. Right now chirpy helps a bit but it is far away from the productivity one has when working within a ruby environment.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Saturday, January 1, 2011 9:50 PM by Mohamed Meligy

@Andrea

I think you can do it developing a custom webforms control that represents your "Box" thing and exposes a Template property that you can use in your pages later. As long as it doesn't require ViewState or <form runat="server" />. But this means using it will be only available in webforms ASP.NET MVC View Engine (unless Razor has a way of calling controls that I don't know of).

Regarding your error, the message reads to me as (since you have "RenderSection()" in your Razor file, we'll treat it as a layout "master page" that you need to use another Razor page and set its layout to this one, not cal this one directly). Note that all Razor files have the same extension not like webforms you have .aspx, .master, etc...

I still think the Box thing should not use layout as you use it. It should either be some way of a Partial, or, it has it's own Controller Action (and then you can use a layout and default ViewPage that does nothing but rendering the Model), and call it in your pages using RenderAction()

Both of which is not possible today as Razor has no way of passing markup as explained in previous comment.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Saturday, January 1, 2011 10:23 PM by Mohamed Meligy

I was hoping that this syntax would work.

@{someObjectProperty =

     <text>

       Time now is @DateTime.Now

     </text>

}

Unfortunately the same issue (cannot assign void to object) caused by the <text> part being directly passed to WriteLiteral() before any further processing.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 12:30 AM by ScottGu

@akachai

>>>>>>> One question on render section, It it possible to do it more declarative way like

>>>>>>> @RenderSection("SideBar")  {

>>>>>>> <p> Default SideBar Content ... </p>

>>>>>>> }

I agree that would be a nice alternative syntax.  Unfortunately it isn't supported with the first release of Razor.  I'll pass it along to the team to look at for a future update.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 9:28 AM by Andrea Bioli

@Mohamed and others

Ok, I made a really silly question! Sometimes having too many instruments is dangerous! :-) My problem was really simpler than I thought.

Just to clarify the situation, here is the solution to the problem I asked help for in the previous posts of mine...

I don't need a partial page with sections, but a normal partial page where I put some custom content with @Html.Partial(...), getting in the parameters the name of the other partial page to render. Something like:

@using MvcApplication1.Models

@model TestModel

<h2>_concretebox</h2>

<div class="boxstyle">

   @Html.Partial(Model.ContentControl)

</div>

Since the name of the partial page to render is taken from the parameters, now I'm able to write code like:

@Html.Partial("_concretebox", new MvcApplication1.Models.TestModel("_content"))

where I want to merge the box and the content. I can even create (obviously) different containers in the concretebox, just augmenting the parameters in the TestModel model.

Now I get the flexibility and reusability I was looking for! :-)

Thanks again to Mohamed, it's not his fault if I missed the whole point!!! :-)

Andrea Bioli

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 1:19 PM by ScottGu

@Mohamed,

>>>>>>>>> One small comment, the use of IsSectionDefined() to add default content is too verbose compared to, for example, the way you do default content in ContentPlaceHolder in webforms MasterPages. I think it needs a better syntax. One possible proposal (not 100% sure about it), is making RenderSection a boolean instead of (assumed) Void. RenderSection() can check IsSectionDefined(), return its value, and render only if the value is true.  It isn't SoC for sure and makes some non-obvious behavior (that's why I'm not sure about it), but then we can write:

>>>>>>>>> @if( ! RenderSection("SideBar") {

>>>>>>>>>   <p>Default SideBar content...</p>

>>>>>>>>> }

It is a good suggestion.  I don't think we can support the exact syntax you proposed - since we return a type from that method that Razor then uses to do the actual rendering (and so can't change it to be a boolean).  But I think we will probably be able to support something like that in a future release of Razor.  

>>>>>>>>> Also, is the tooling aware somehow of all sections defined in a layout? Can it generate sections when creating a View based on the sections defined in the layout (reflecting on ContentPlaceHolders and MasterPages again)? I assume this might be harder to tell from the layout but it'll be nice if it can be obtained and even have intellisense for it. If it's not possible, I'll hope in extensions like Resharper or T4MVC to do it.

The tooling can be aware of sections - although one difference from the WebForms view engine is that layouts are associated in code as opposed to via a declarative syntax.  This means that there are more situations where you can associate layouts with views that the tools could never figure out (for example: via a CMS system).  This ends up being much more powerful/flexible - but does mean that certain scenarios can automatically be deduced simply by looking at a view.  In the next release we will likely add additional tooling support to allow people to optionally scaffold sections if they are defined in a layout it depends on.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 1:33 PM by ScottGu

@Mohamed and @Andrea,

>>>>>>>> Yeah, your problem is what is solved by ITemplate or template controls in webforms. The controls composition model is the best part of webforms, not yet to see a near-powerful composition model for ASP.NET MVC.  One thing that can help this if implemented in ASP.NET MVC is being able to pass a block of text/code to Razor statement. You can already do:

>>>>>>>> if (...) {

>>>>>>>>   <p> Some markup and @"code" here

>>>>>>>> }

>>>>>>>> It'll be great if you can do something like:

>>>>>>>> @someProperty = {

>>>>>>>>   <p> Some markup and @"code" here</p>

>>>>>>>> }

The ability to pass in inline templates to HTML helpers is actually supported with Razor (albeit it is an advanced scenario)  I haven't blogged about it yet which makes it even more indiscoverable :-)

Check out Marcin's post here where he shows a little of what is possible: blogs.msdn.com/.../optional-razor-sections-with-default-content.aspx

Andrew Nurse also has a blog post that talks a little about them here: blog.andrewnurse.net/CommentView,guid,56056f45-920f-487c-ba80-0c53c3e44a97.aspx

This allows you to write code like:

   Html.MyCustomList(Products, "@<div>Name: @item.ProductName</div");

Where you are passing in an inline template as an argument to the method - and that template can have both HTML as well as inline Razor code expressions that can be evaluated (any number of times) by the helper.

I'll try and do a blog post on how to use this handy feature in the future.  It is a little advanced, but extremely powerful and provides something like the ITemplate composibility support we have in Web Forms.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 1:47 PM by ScottGu

@Martin,

>>>>>>> I want to change from razor view engine to another view engine (markdown in my case) within a razor view. Is that possible, and if so how?

The best way to do this is by using a Partial.  You can have a Razor view call out to a partial built with Markdown (or .aspx or NHaml, etc) without problems.  Just call:

  @Html.Partial("MyPartialName")

And then that section of the output will be owned by your Markdown partial.  You can optionally pass additional data to the partial as well if you want to scope its model to be a subset of the overall view's model.

>>>>>>> PS: It would be really great for the next release of asp.net mvc if you would support sass and a system like compass for css and javascript. It's a shame that we are still creating css like it's 1996 on Microsoft platforms. Right now chirpy helps a bit but it is far away from the productivity one has when working within a ruby environment.

One of the reasons we are including NuGet with MVC 3 is to enable both the community (and us) to ship components like this without having to wait for the next major release of MVC.  You'll see us ship several packages via NuGet this spring - including a lot richer scaffolding support as an example (first release of this should be out later this month).  I'll forward the SASS request onto the team so that they can investigate either supporting an existing OSS project that does it or potentially sponsor one ourselves.  But I think you'll see richer support for this soon.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 4:41 PM by ScottGu

@Andrea,

Cool - glad you got it working!

Thanks,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, January 2, 2011 9:58 PM by Rodrigo Caballero

Hi Scott,

I can't wait for the MVC 3's final version. I wonder if you will include the Html's Serialize extension method (from the futures version). unfortunately, I cannot find any other way to persist some of my ViewModel's collection properties without going to the database for each post action(I know Session can be the obvious way...)

best regards

rodrigo

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 3, 2011 11:52 AM by Tim Cartwright

>>>>>>>>

@Tim,

>>>>>>>> Ok, I read through all of your posts, and I do have a question that is not answered in any of them. How do you do localization with Razor?

Generally we recommend using the resource model that is built-into ASP.NET to handle localization with Razor. Because you use standard VB and C# code within Razor templates, you get access to all of the standard localization/resource APIs available with .NET.

Hope this helps,

Scott>>>>>>>>

Scott, could you do an example for one of your posts?

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 3, 2011 12:12 PM by MartinFro

How do i use Conditional Compilation statements with Razor ?

@#if debug

....

@endif

doesnt work!

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 3, 2011 1:44 PM by MartinFro

Using @Html.RenderPartial() from a Razor view doesnt work.

It returns void but expects a HelperResult

Error 1 The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments c:\Users\Martin\Projects\Whatever\Source\Whatever.Web\Views\Shared\_Layout.cshtml 129 Whatever.Web

Error 2 Argument 1: cannot convert from 'void' to 'System.Web.WebPages.HelperResult' c:\Users\Martin\Projects\Whatever\Source\Whatever.Web\Views\Shared\_Layout.cshtml 129 Whatever.Web

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 3, 2011 3:51 PM by pcyoung

Is it possible for Layout.cshtml to know which page is calling it (Index.cshtml vs About.cshtml)? Other than using "PATH_INFO" or "SCRIPT_NAME"

I could see this becoming an easy solution for the poor-mans menu which knows which page it is presently displaying.  Of course this goes out the window when AJax is making dynamic DIV content, but it would still be nice to know how to do it.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 3, 2011 4:31 PM by ScottGu

@MartinFro,

>>>>>> Using @Html.RenderPartial() from a Razor view doesnt work.

Rather than call Html.RenderPartial() use just @Html.Partial("partialname")

That returns a string and will work.  

Alternatively, if you really want to use the void return method you can use this syntax:

@{

  Html.RenderPartial("partialName")

}

But @Html.Partial() is the cleanest.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Tuesday, January 4, 2011 9:40 AM by MartinFro

Thanks Scott, i also found out about the conditional debug statements - just need to use @{ #IF DEBUG ... }

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 5, 2011 3:08 AM by ScottGu

@Rodrigo,

>>>>>>> I can't wait for the MVC 3's final version. I wonder if you will include the Html's Serialize extension method (from the futures version). unfortunately, I cannot find any other way to persist some of my ViewModel's collection properties without going to the database for each post action(I know Session can be the obvious way...)

The Html.Serialize() extension method will still live in the MVC Futures extension.  The good news, though, is that NuGet will make it much easier to install and use it.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 5, 2011 3:10 AM by ScottGu

@Tim,

>>>>>>>> Ok, I read through all of your posts, and I do have a question that is not answered in any of them. How do you do localization with Razor?

You should be able to use standard ASP.NET localization techniques with Razor.  Create a App_GlobalResources folder and add your resource files there. Then in Razor just output the resource property. (Regular resource files elsewhere should also work but you’ll have to make their accessors public so that the dynamically compiled views can see them):

@Resources.MyResourceType.Property

There’s no special syntax for resources in Razor a’la WebForms but we might consider adding something in v2.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 5, 2011 3:11 AM by ScottGu

@pcyoung,

>>>>>>>> Is it possible for Layout.cshtml to know which page is calling it (Index.cshtml vs About.cshtml)? Other than using "PATH_INFO" or "SCRIPT_NAME"  I could see this becoming an easy solution for the poor-mans menu which knows which page it is presently displaying.  Of course this goes out the window when AJax is making dynamic DIV content, but it would still be nice to know how to do it.

The code within a view runs first (before the layout).  So you can have code in the view pass data to the layout via the ViewBag property (like we do above with the ViewBag.Title line of code).  If you wanted to, you could use an approach like this to indicate what page is being rendered and what the layout should do with it.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, January 6, 2011 3:35 AM by Jeepr

I can't seem to get sections working from a partial layout.

_Layout.cshtml:

@RenderSection("CssPageExt", required: false)

Form.cshtml

@Html.Partial("Panel");

Panel.cshtml

@* no error-message, but doesn't do anything *@

@section CssPageExt {

<link href="main.css" type="text/css" rel="stylesheet" />

}

When placing the @section code in Form.cshtml it works perfectly.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 10, 2011 12:44 PM by pcyoung

I'm trying for DRY code so I am trying to combine partial and full views like so:

@{

/*** Should we render a full page or just the content to be used in an Ajax with a target?. */

//if (ViewBag.IsPartial)

if (Request.IsAjaxRequest())

   {

       Layout = null;

   } else

   {

       ViewBag.Title = "MyApp (About)";

<text>@section SideBar {<p>SideBar (About)</p>}</text>

//DefineSection(string name, ActionWriter action)?

//DefineSection("SideBar", {"<p>My Sidebar Content</p>"});

   }

}

<h2>About</h2>

<p>Some text here...</p>

NOTICE that I had to use <text> blocks around it to make it work; is that by design or is there a way to actually define and ActionWriter on the fly?

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 10, 2011 2:12 PM by ScottGu

@Jeepr,

Send me email (scottgu@microsoft.com) if you are still having issues and I can connect you with someone to help.

Thanks,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Monday, January 10, 2011 2:14 PM by ScottGu

@pcyoung,

To keep things DRY, I'd recommend doing a @Html.Action() call within your mail page that calls out to an action method on a controller which returns a PartialView().  This way the code to encapsulate the logic to render the partial is in one place.  One important thing to make sure you do is to return a "PartialView()" as opposed to a "View()" to make sure that it doesn't render the Layout.

You can then optionally call the action from the client as well to refresh just that region using AJAX.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Tuesday, January 11, 2011 8:07 AM by Florin Gugui

@Andrea Bioli,

I have a application where I should use the same solution you were looking for. Could you, please, share a small example, to be more detailed on the solution you found?

Thanks.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 12, 2011 10:48 AM by Kyaw

Razor looks great. How do we dynamically change Layout(master page) if an application needs to allow multiple page template layout?

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 12, 2011 3:40 PM by pcyoung

Ok, so is it possible for a partial page to define and/or change a section?

Index.cshtml:

@{

ViewBag.Title = "FltPay (Home)";

//<text>@section contentMenu { }</text>

}

@section contentBody { @Html.Action(

actionName: "Welcome",

controllerName: "Home",

routeValues: new { IsPartial = true, LoadMenu = false })}

<h2>Index</h2>

<p>Some text...</p>

Welcome.cshtml:

@{

if (ViewBag.IsPartial == true)

{

Layout = null;

} else

{

ViewBag.Title = "MyApp (Welcome)";

}

}

@section contentMenu {<p>Welcome Menu</p> }

<h2>Welcome</h2>

<p>Some text here...</p>

I cannot get the section "contentMenu" to update when it is defined on a partial page.

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Thursday, January 13, 2011 7:57 AM by pcyoung

UPDATE to previous comment (Wednesday, January 12, 2011 8:40 PM):

I need to be able to define a section in either a PartialView or in the _ViewStart and I cannot figure out how to do either.

When I try to define a section in a PartialView I get no error but nothing happens.

When I try to define a section in the _ViewStart I get an error: "CS0103: The name 'DefineSection' does not exist in the current context" ... "Line 55: DefineSection("contentMenu", () => {" ...

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 26, 2011 12:29 AM by LaBowski

Hey Scott,

I feel like an idiot... I've watched your video and read your blog posts. I can't figure out how/where to upload the images from my graphic designer to be used in CSS etc. Even just adding the logo in a <a href...

I appreciate your time and apologize if this is a stupid question... :(

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, January 26, 2011 1:47 AM by ScottGu

@LaBowski,

>>>>>>  I can't figure out how/where to upload the images from my graphic designer to be used in CSS etc. Even just adding the logo in a <a href...

Not a problem!  Typically with ASP.NET MVC apps you put those within the \Content folder of the project.  You can then reference it using a URL like: /Content/MyImage.jpg

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Tuesday, February 1, 2011 11:45 PM by SureshM

Similar concept of Rails...Layout and Partial (section) in ASPMVC...

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, February 2, 2011 7:40 PM by Roberto Hernandez

Is it possible to have a section name with a "-" in it?

Like:

@RenderSection("page-info", required: false)

Roberto.-

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Wednesday, February 2, 2011 10:51 PM by ScottGu

@Roberto,

>>>>>> Is it possible to have a section name with a "-" in it?

No - dashes are not allowed.  However you can use underscores.  So "page_info" could be used.

Hope this helps,

Scott

# re: ASP.NET MVC 3: Layouts and Sections with Razor

Sunday, February 13, 2011 5:13 AM by Zak

Hi, just to ask a question and commend the effort and quality.

I am using @RenderSection("headerIncludes",required:false), set in head of _Layout.cshtml

to include specific script and CSS files only on pages where i need them.

It all works fine when i add the @section ... part in certain view, it all gets included.

But when i add the @section... to partial view that is included in certain view via @Html.Partial(...)

then the code in @section... does not get included in final webform, while all the rest of partial view is included correctly. Can You recommend a solution that keeps the code separated like this?

Thank You