Search code examples
asp.net-corerazor

Razor template/component solution that supports child Razor markup


Is there a template/component solution in ASP.NET Core Razor, that supports inner Razor markup?

Here's a use case:

1. Say I have some repetitive markup for example "a div with nice borders, shadows and two buttons at the bottom"

2. Obviously this markup has a common "header" and a "footer" in the HTML code

3. I need to pass arbitrary Razor markup to insert between header and footer. Not just a model object - but some actual markup that will be rendered between header and footer. I can't use foreach because this markup is different every time - it can be text-content, a form, an image, or some complicated Razor-rendered stuff.

Basically I'm looking for a "Surround this Razor with more Razor" templating solution

Something like:

@{
    //this function renders my beautiful box
    Func<dynamic, IHtmlContent> myFunction = @<div class="relative flex flex-col rounded-2xl border border-gray-200 bg-white p-8 shadow-sm">
        @item
    </div>;
}

<!-- and then I call it passing some Razor as input -->
@myFunction(
    <ul>
        <li>@SomeRazorMethod()</li>
    </ul>

);

Something like a Layout - but the one I can use multiple times on the same page.

Is there anything like that? This is a pretty common componentizing tool - "wrap my markup with other markup" - that is present in other templating engines (React, Vue, etc), but apparently not in Razor.

Just to be clear: I'm looking for a Razor-based solution, not a C#-based one. So that my header-footer markup stays in markup files (.cshtml), not in C# files that will have hard-coded HTML magic strings.


Solution

  • @Shah's answer got me one step closer to a solution, however, it seems like the the actual question I'm trying to solve is "can I pass Razor markup as an input parameter".

    Turns out you can, you just have to put @ in front of it:

    @{
        void MyFunc(Func<object, IHtmlContent> template)
        {
            <div>@template(null)</div>
        }
    }
    
    
    @{ MyFunc(@<div>The ID is: @Model.Id</div>); }
    <!-- mind the '@' before the 'div' -->