RazorViewComponent 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package RazorViewComponent --version 1.0.0                
NuGet\Install-Package RazorViewComponent -Version 1.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RazorViewComponent" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add RazorViewComponent --version 1.0.0                
#r "nuget: RazorViewComponent, 1.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install RazorViewComponent as a Cake Addin
#addin nuget:?package=RazorViewComponent&version=1.0.0

// Install RazorViewComponent as a Cake Tool
#tool nuget:?package=RazorViewComponent&version=1.0.0                

<img src="Logo.png" alt="project icon" />

RazorViewComponent

What is it?

RazorViewComponent is a mashup of existing ASP.NET technologies that makes it very easy to create and use UI components in your Razor Pages projects.

<br>

Here is a sample of what it lets you do:


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

<div>
	
	<bs5-card 
		title="Sample Title" 
		subTitle="Sample Sub-Title"
		cardCss="my-3">

		<p>Some content for my sample card.</p>

		<card-header>
			<p>Some content for the card header</p>
		</card-header>
		<card-footer>
			<p>Some content for the card footer</p>
		</card-footer>
	</bs5-card>
</div>

<br>

Okay, but how easy is it really?

Very easy, actually!

Add the nuget package to your project...

dotnet add package RazorViewComponent

Update View Imports...

// /Pages/_ViewImports.cshtml
@using WebApp1
@namespace WebApp1.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

// *** ADD THIS LINE ***
@addTagHelper *, WebApp1

Define the component...

// BootstrapCard.cshtml.cs
using Microsoft.AspNetCore.Razor.TagHelpers;
using RazorViewComponent;

namespace WebApp1.Pages.Shared.Components
{
	[HtmlTargetElement("bs5-card")]
	public class BootstrapCard : RazorViewComponent
	{
		[HtmlAttributeName("title")]
		public string? CardTitle { get; set; }

		[HtmlAttributeName("subTitle")]
		public string? CardSubTitle { get; set; }

		[HtmlAttributeName("cardCss")]
		public string? CardCss { get; set; }
	}

	[HtmlTargetElement("card-header")]
	public class BootstrapCardHeader : AutoNamedSlotComponent { }

	[HtmlTargetElement("card-footer")]
	public class BootstrapCardFooter : AutoNamedSlotComponent { }

	// NOTE: Don't worry about 'magic' strings. I used them here only 
	// for the sake of brevity. Take a look at the sample project to 
	// see how to use constants to eliminate 'magic' strings.
}

And its view...


@model BootstrapCard;

<div class="card @Model.CardCss">
	@if (Model.SlotHasContent("card-header"))
	{
		<div class="card-header">
			@Model.RenderSlot("card-header")
		</div>
	}
	<div class="card-body">
		@if (Model.CardTitle is not null)
		{
			<h5 class="card-title">@Model.CardTitle</h5>
		}
		@if (Model.CardSubTitle is not null)
		{
			<h6 class="card-subtitle">@Model.CardSubTitle</h6>
		}
		@if (Model.HasChildContent())
		{
			<div class="mt-2">
				@Model.RenderChildContent()
			</div>
		}
	</div>
	@if (Model.SlotHasContent("card-footer"))
	{
		<div class="card-footer">
			@Model.RenderSlot("card-footer")
		</div>
	}
</div>

And, that's really all there is to it!

<br>

You have quite a bit of flexibility in what your components can do. You could, for instance, inject a service into your component to query a database based on the value of one of the components attributes (e.g. productId) in order to display product data in a consistent, component-based UI element. While that's not an especially practical example, it does illustrate the flexibility available to you. A more realistic approach would be to just provide a pre-populated Product object to your component.

<br>

Configuration

Location of view files

By default, RazorViewComponent looks for views associated with a component in the /Shared/Components subfolder under /Pages (i.e. /Pages/Shared/Components/*.cshtml). It uses the component's class name (without the 'Component' suffix, if present) as the view file name. So, as an example, for a component class named MyViewComponent, the pathname for its associated view file would be /Pages/Shared/Components/MyView.cshtml.

This path configuration applies only to component view (*.cshtml) files; the *.cs file containing the component's class declaration can be located anywhere in your project. It is only a convention to place the .cs and .cshtml files in the same location (e.g. MyView.cshtml.cs and MyView.cshtml).

The reason why component view files must be located under the /Pages folder is that RazorViewComponent uses the partial-view rendering capabilities built into ASP.NET to render component views. Accordingly, view files must be located somewhere the ASP.NET Razor view engine can find them, which by default in a Razor Pages project is the /Pages folder. The configuration for the Razor view engine in ASP.NET can be modified, of course, in the call to services.AddRazorPages().

IMPORTANT: If you change the location where ASP.NET searches for (partial) view files, you must also relocate the /Pages/Shared/Components/ folder to that new location (e.g. /NewPagesFolder/Shared/Components).

You can specify a different folder where RazorViewComponent should look for component view files by configuring an instance of RazorViewComponentOptions using a services.Configure<T>() call. For example, the following will change the folder where RazorViewComponent looks for views to /Pages/MyComponents.

services.Configure<RazorViewComponentOptions>(
	options =>
	{
		options.ViewFilesLocation = "/MyComponents";
	});

IMPORTANT: In all cases, the folder containing component view files must be a subfolder under the root folder (or the root folder itself) where ASP.NET will search for view files (i.e. /Pages, by default).

Limitations

RazorViewComponent currently has the following limitations:

  • Slots with no content will throw an exception. This is a pretty easy fix, but I'm not sure if it's something that should actually be allowed. I'm leaning toward yes, allow it!
    <my-component>
      <my-slot>
      </my-slot>
    </my-component>
    
  • Supports only one instance of a named slot in a component — you cannot declare the same slot more than once. This can certainly be addressed with a bit of work, but it's still under review/consideration as to whether it's useful in a practical sense.
    <my-component>
    
      <my-slot>...</my-slot>
    
      <my-slot>...</my-slot>
    </my-component>
    
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.0 228 12/7/2023
1.1.0 120 12/6/2023
1.0.0 126 12/5/2023