Alexander Zeitler

Alexander Zeitler

ASP.NET Razor Pages Fragments / Single View approach

Published on Friday, January 27, 2023

Photo by Olga Deeva on Unsplash

I got some feedback for my previous post: Will the single view approach work with ASP.NET Razor Pages instead of MVC Views and Controllers?

Well, I'm a total Razor Pages noob, but this didn't stop me to give it a try.

Long story short: it works, but I might be doing it totally wrong.

Here's the source:

Biggest issue upfront: how do we get multiple GET handlers in our Page Model?

Jerrie Pelser has a post that solved it for me.

Our Page now has this route template:

@page "{handler?}"

This makes stuff dynamic, and we can end up having multiple GET requests within the same Code for the page.

Thus, our page looks very similar to our MVC View except for the Model which is now a child property if the Page Model:

@page "{handler?}"
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

@{
    void RenderDetail(ChildModel child)
    {
        <div class="bg-gray-200">
            <a href="@Url.PageLink("Index", "Details", new {Id = child.Id})">@child.Id</a>
        </div>
    }

    void RenderFull(ParentModel parent)
    {
    <div class="bg-blue-500 p-4">
        @{
        @foreach (var parentChild in parent.Childs)
        {
        RenderDetail(parentChild);
        }
        }
    </div>
    }
}


@{
    switch (Model.PageModel.FragmentId)
    {
        case "Full":
            RenderFull(Model.PageModel as ParentModel);
            break;
        case "Detail":
            RenderDetail(Model.PageModel as ChildModel);
            break;
        default:
            throw new ArgumentOutOfRangeException();
    }
}

The page model looks like this:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesFragments.Pages;

public class IndexModel : PageModel
{
  private readonly ILogger<IndexModel> _logger;
  public FragmentModel PageModel { get; set; } = null!;

  public IndexModel(
    ILogger<IndexModel> logger
  )
  {
    _logger = logger;
  }

  public void OnGet()
  {
    PageModel = new ParentModel(
      new List<ChildModel>()
      {
        new(1),
        new(2)
      }
    );
  }

  public void OnGetDetails(
    [FromQuery] int id
  )
  {
    PageModel = new ChildModel(id);
  }
}

public class FragmentModel
{
  public FragmentModel(
    string fragmentId
  )
  {
    FragmentId = fragmentId;
  }

  public string FragmentId { get; set; }
}

public class ChildModel : FragmentModel
{
  public int Id { get; }

  public ChildModel(
    int id
  ) : base("Detail")
  {
    Id = id;
  }
}

public class ParentModel : FragmentModel
{
  public List<ChildModel> Childs { get; }

  public ParentModel(
    List<ChildModel> childs
  ) : base("Full")
  {
    Childs = childs;
  }
}

And that's it.

If I have missed something due to my lack of Razor Pages knowledge, feel fry to drop me a line how to improve it.

The full sample can be found on GitHub.

What are your thoughts about "ASP.NET Razor Pages Fragments / Single View approach"?
Drop me a line - I'm looking forward to your feedback! email
Imprint | Privacy