Create reusable UI using the Razor class library project in ASP.NET Core
Razor views, pages, controllers, page models, Razor components, View components, and data models can be built into a Razor class library (RCL). The RCL can be packaged and reused. Applications can include the RCL and override the views and pages it contains. When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence.
For information on how to integrate npm and webpack into the build process for a RCL, see Build client web assets for your Razor Class Library.
Create a class library containing Razor UI
- From Visual Studio select Create new a new project.
- Select Razor Class Library > Next.
- Name the library (for example, "RazorClassLib"), > Create. To avoid a file name collision with the generated view library, ensure the library name doesn't end in
.Views
. - Select Support pages and views if you need the library to contain pages and/or views. By default, only Razor components are supported. Select Create.
The Razor Class Library template defaults to Razor component development by default. The Support pages and views option supports pages and views. For more information on RCL support in Blazor, see Consume ASP.NET Core Razor components from a Razor class library (RCL).
Add Razor files to the RCL.
The ASP.NET Core templates assume the RCL content is in the Areas
folder. See RCL Pages layout below to create an RCL that exposes content in ~/Pages
rather than ~/Areas/Pages
.
Reference RCL content
The RCL can be referenced by:
- NuGet package. See Creating NuGet packages and dotnet add package and Create and publish a NuGet package.
{ProjectName}.csproj
. See dotnet-add reference.
Override views, partial views, and pages
When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence. For example, add WebApp1/Areas/MyFeature/Pages/Page1.cshtml
to WebApp1, and Page1 in the WebApp1 will take precedence over Page1 in the RCL.
In the sample download, rename WebApp1/Areas/MyFeature2
to WebApp1/Areas/MyFeature
to test precedence.
Copy the RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
partial view to WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml
. Update the markup to indicate the new location. Build and run the app to verify the app's version of the partial is being used.
If the RCL uses Razor Pages, enable the Razor Pages services and endpoints in the hosting app:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
RCL Pages layout
To reference RCL content as though it is part of the web app's Pages
folder, create the RCL project with the following file structure:
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
Suppose RazorUIClassLib/Pages/Shared
contains two partial files: _Header.cshtml
and _Footer.cshtml
. The <partial>
tags could be added to _Layout.cshtml
file:
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
Add the _ViewStart.cshtml
file to the RCL project's Pages
folder to use the _Layout.cshtml
file from the host web app:
@{
Layout = "_Layout";
}
Create an RCL with static assets
An RCL may require companion static assets that can be referenced by either the RCL or the consuming app of the RCL. ASP.NET Core allows creating RCLs that include static assets that are available to a consuming app.
To include companion assets as part of an RCL, create a wwwroot
folder in the class library and include any required files in that folder.
When packing an RCL, all companion assets in the wwwroot
folder are automatically included in the package.
Use the dotnet pack
command rather than the NuGet.exe version nuget pack
.
Add client web assets to the build process
Integrating client web assets into the build pipeline is nontrivial. See Build client web assets for your Razor Class Library for more information.
Exclude static assets
To exclude static assets, add the desired exclusion path to the $(DefaultItemExcludes)
property group in the project file. Separate entries with a semicolon (;
).
In the following example, the lib.css
stylesheet in the wwwroot
folder isn't considered a static asset and isn't included in the published RCL:
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript integration
To include TypeScript files in an RCL:
Reference the
Microsoft.TypeScript.MSBuild
NuGet package in the project.Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Place the TypeScript files (
.ts
) outside of thewwwroot
folder. For example, place the files in aClient
folder.Configure the TypeScript build output for the
wwwroot
folder. Set theTypescriptOutDir
property inside of aPropertyGroup
in the project file:<TypescriptOutDir>wwwroot</TypescriptOutDir>
Include the TypeScript target as a dependency of the
PrepareForBuildDependsOn
target by adding the following target inside of aPropertyGroup
in the project file:<PrepareForBuildDependsOn> CompileTypeScript; GetTypeScriptOutputForPublishing;$(PrepareForBuildDependsOn) </PrepareForBuildDependsOn>
Consume content from a referenced RCL
The files included in the wwwroot
folder of the RCL are exposed to either the RCL or the consuming app under the prefix _content/{PACKAGE ID}/
. For example, a library with an assembly name of Razor.Class.Lib
and without a <PackageId>
specified in its project file results in a path to static content at _content/Razor.Class.Lib/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
.
The consuming app references static assets provided by the library with <script>
, <style>
, <img>
, and other HTML tags. The consuming app must have static file support enabled in:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
When running the consuming app from build output (dotnet run
), static web assets are enabled by default in the Development environment. To support assets in other environments when running from build output, call UseStaticWebAssets on the host builder in Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseWebRoot("wwwroot");
builder.WebHost.UseStaticWebAssets();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Calling UseStaticWebAssets
isn't required when running an app from published output (dotnet publish
).
Multi-project development flow
When the consuming app runs:
- The assets in the RCL stay in their original folders. The assets aren't moved to the consuming app.
- Any change within the RCL's
wwwroot
folder is reflected in the consuming app after the RCL is rebuilt and without rebuilding the consuming app.
When the RCL is built, a manifest is produced that describes the static web asset locations. The consuming app reads the manifest at runtime to consume the assets from referenced projects and packages. When a new asset is added to an RCL, the RCL must be rebuilt to update its manifest before a consuming app can access the new asset.
Publish
When the app is published, the companion assets from all referenced projects and packages are copied into the wwwroot
folder of the published app under _content/{PACKAGE ID}/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
when examining the wwwroot
folder for the published assets.
Additional resources
Razor views, pages, controllers, page models, Razor components, View components, and data models can be built into a Razor class library (RCL). The RCL can be packaged and reused. Applications can include the RCL and override the views and pages it contains. When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence.
For information on how to integrate npm and webpack into the build process for a Razor Class Library, see Build client web assets for your Razor Class Library.
Create a class library containing Razor UI
- From Visual Studio select Create new a new project.
- Select Razor Class Library > Next.
- Name the library (for example, "RazorClassLib"), > Create. To avoid a file name collision with the generated view library, ensure the library name doesn't end in
.Views
. - Select Support pages and views if you need to support views. By default, only Razor Pages are supported. Select Create.
The Razor class library (RCL) template defaults to Razor component development by default. The Support pages and views option supports pages and views.
Add Razor files to the RCL.
The ASP.NET Core templates assume the RCL content is in the Areas
folder. See RCL Pages layout below to create an RCL that exposes content in ~/Pages
rather than ~/Areas/Pages
.
Reference RCL content
The RCL can be referenced by:
- NuGet package. See Creating NuGet packages and dotnet add package and Create and publish a NuGet package.
{ProjectName}.csproj
. See dotnet-add reference.
Override views, partial views, and pages
When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence. For example, add WebApp1/Areas/MyFeature/Pages/Page1.cshtml
to WebApp1, and Page1 in the WebApp1 will take precedence over Page1 in the RCL.
In the sample download, rename WebApp1/Areas/MyFeature2
to WebApp1/Areas/MyFeature
to test precedence.
Copy the RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
partial view to WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml
. Update the markup to indicate the new location. Build and run the app to verify the app's version of the partial is being used.
If the RCL uses Razor Pages, enable the Razor Pages services and endpoints in the hosting app:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
RCL Pages layout
To reference RCL content as though it is part of the web app's Pages
folder, create the RCL project with the following file structure:
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
Suppose RazorUIClassLib/Pages/Shared
contains two partial files: _Header.cshtml
and _Footer.cshtml
. The <partial>
tags could be added to _Layout.cshtml
file:
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
Add the _ViewStart.cshtml
file to the RCL project's Pages
folder to use the _Layout.cshtml
file from the host web app:
@{
Layout = "_Layout";
}
Create an RCL with static assets
An RCL may require companion static assets that can be referenced by either the RCL or the consuming app of the RCL. ASP.NET Core allows creating RCLs that include static assets that are available to a consuming app.
To include companion assets as part of an RCL, create a wwwroot
folder in the class library and include any required files in that folder.
When packing an RCL, all companion assets in the wwwroot
folder are automatically included in the package.
Use the dotnet pack
command rather than the NuGet.exe version nuget pack
.
Exclude static assets
To exclude static assets, add the desired exclusion path to the $(DefaultItemExcludes)
property group in the project file. Separate entries with a semicolon (;
).
In the following example, the lib.css
stylesheet in the wwwroot
folder isn't considered a static asset and isn't included in the published RCL:
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript integration
To include TypeScript files in an RCL:
Reference the
Microsoft.TypeScript.MSBuild
NuGet package in the project.Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Place the TypeScript files (
.ts
) outside of thewwwroot
folder. For example, place the files in aClient
folder.Configure the TypeScript build output for the
wwwroot
folder. Set theTypescriptOutDir
property inside of aPropertyGroup
in the project file:<TypescriptOutDir>wwwroot</TypescriptOutDir>
Include the TypeScript target as a dependency of the
PrepareForBuildDependsOn
target by adding the following target inside of aPropertyGroup
in the project file:<PrepareForBuildDependsOn> CompileTypeScript; GetTypeScriptOutputForPublishing;$(PrepareForBuildDependsOn) </PrepareForBuildDependsOn>
Consume content from a referenced RCL
The files included in the wwwroot
folder of the RCL are exposed to either the RCL or the consuming app under the prefix _content/{PACKAGE ID}/
. For example, a library with an assembly name of Razor.Class.Lib
and without a <PackageId>
specified in its project file results in a path to static content at _content/Razor.Class.Lib/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
.
The consuming app references static assets provided by the library with <script>
, <style>
, <img>
, and other HTML tags. The consuming app must have static file support enabled in:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
When running the consuming app from build output (dotnet run
), static web assets are enabled by default in the Development environment. To support assets in other environments when running from build output, call UseStaticWebAssets on the host builder in Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseWebRoot("wwwroot").UseStaticWebAssets();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Note: .NET 6 only requires calling builder.WebHost.UseWebRoot("wwwroot").UseStaticWebAssets
. For more information, see this GitHub issue.
Calling UseStaticWebAssets
isn't required when running an app from published output (dotnet publish
).
Multi-project development flow
When the consuming app runs:
- The assets in the RCL stay in their original folders. The assets aren't moved to the consuming app.
- Any change within the RCL's
wwwroot
folder is reflected in the consuming app after the RCL is rebuilt and without rebuilding the consuming app.
When the RCL is built, a manifest is produced that describes the static web asset locations. The consuming app reads the manifest at runtime to consume the assets from referenced projects and packages. When a new asset is added to an RCL, the RCL must be rebuilt to update its manifest before a consuming app can access the new asset.
Publish
When the app is published, the companion assets from all referenced projects and packages are copied into the wwwroot
folder of the published app under _content/{PACKAGE ID}/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
when examining the wwwroot
folder for the published assets.
Additional resources
Razor views, pages, controllers, page models, Razor components, View components, and data models can be built into a Razor class library (RCL). The RCL can be packaged and reused. Applications can include the RCL and override the views and pages it contains. When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence.
View or download sample code (how to download)
Create a class library containing Razor UI
- From Visual Studio select Create a new project.
- Select Razor Class Library > Next.
- Name the library (for example, "RazorClassLib"), > Create > Next. To avoid a file name collision with the generated view library, ensure the library name doesn't end in
.Views
. - Select the Target Framework. Check ☑ Support pages and views to support views. By default, only Razor components are supported. Select Create.
The Razor class library (RCL) template defaults to Razor component development by default. The Support pages and views option supports pages and views.
Add Razor files to the RCL.
The ASP.NET Core templates assume the RCL content is in the Areas
folder. See RCL Pages layout to create an RCL that exposes content in ~/Pages
rather than ~/Areas/Pages
.
Reference RCL content
The RCL can be referenced by:
- NuGet package. See Creating NuGet packages and dotnet add package and Create and publish a NuGet package.
{ProjectName}.csproj
. See dotnet-add reference.
Override views, partial views, and pages
When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence. For example, add WebApp1/Areas/MyFeature/Pages/Page1.cshtml
to WebApp1, and Page1 in the WebApp1 will take precedence over Page1 in the RCL.
In the sample download, rename WebApp1/Areas/MyFeature2
to WebApp1/Areas/MyFeature
to test precedence.
Copy the RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
partial view to WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml
. Update the markup to indicate the new location. Build and run the app to verify the app's version of the partial is being used.
RCL Pages layout
To reference RCL content as though it is part of the web app's Pages
folder, create the RCL project with the following file structure:
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
Suppose RazorUIClassLib/Pages/Shared
contains two partial files: _Header.cshtml
and _Footer.cshtml
. The <partial>
tags could be added to _Layout.cshtml
file:
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
Add the _ViewStart.cshtml
file to the RCL project's Pages
folder to use the _Layout.cshtml
file from the host web app:
@{
Layout = "_Layout";
}
Create an RCL with static assets
An RCL may require companion static assets that can be referenced by either the RCL or the consuming app of the RCL. ASP.NET Core allows creating RCLs that include static assets that are available to a consuming app.
To include companion assets as part of an RCL, create a wwwroot
folder in the class library and include any required files in that folder.
When packing an RCL, all companion assets in the wwwroot
folder are automatically included in the package.
Use the dotnet pack
command rather than the NuGet.exe version nuget pack
.
Exclude static assets
To exclude static assets, add the desired exclusion path to the $(DefaultItemExcludes)
property group in the project file. Separate entries with a semicolon (;
).
In the following example, the lib.css
stylesheet in the wwwroot
folder isn't considered a static asset and isn't included in the published RCL:
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript integration
To include TypeScript files in an RCL:
Reference the
Microsoft.TypeScript.MSBuild
NuGet package in the project.Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Place the TypeScript files (
.ts
) outside of thewwwroot
folder. For example, place the files in aClient
folder.Configure the TypeScript build output for the
wwwroot
folder. Set theTypescriptOutDir
property inside of aPropertyGroup
in the project file:<TypescriptOutDir>wwwroot</TypescriptOutDir>
Include the TypeScript target as a dependency of the
ResolveCurrentProjectStaticWebAssets
target by adding the following target inside of aPropertyGroup
in the project file:<ResolveCurrentProjectStaticWebAssetsInputsDependsOn> CompileTypeScript; $(ResolveCurrentProjectStaticWebAssetsInputs) </ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
Consume content from a referenced RCL
The files included in the wwwroot
folder of the RCL are exposed to either the RCL or the consuming app under the prefix _content/{PACKAGE ID}/
. For example, a library with an assembly name of Razor.Class.Lib
and without a <PackageId>
specified in its project file results in a path to static content at _content/Razor.Class.Lib/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
.
The consuming app references static assets provided by the library with <script>
, <style>
, <img>
, and other HTML tags. The consuming app must have static file support enabled in Startup.Configure
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseStaticFiles();
...
}
When running the consuming app from build output (dotnet run
), static web assets are enabled by default in the Development environment. To support assets in other environments when running from build output, call UseStaticWebAssets
on the host builder in Program.cs
:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets();
webBuilder.UseStartup<Startup>();
});
}
Calling UseStaticWebAssets
isn't required when running an app from published output (dotnet publish
).
Multi-project development flow
When the consuming app runs:
- The assets in the RCL stay in their original folders. The assets aren't moved to the consuming app.
- Any change within the RCL's
wwwroot
folder is reflected in the consuming app after the RCL is rebuilt and without rebuilding the consuming app.
When the RCL is built, a manifest is produced that describes the static web asset locations. The consuming app reads the manifest at runtime to consume the assets from referenced projects and packages. When a new asset is added to an RCL, the RCL must be rebuilt to update its manifest before a consuming app can access the new asset.
Publish
When the app is published, the companion assets from all referenced projects and packages are copied into the wwwroot
folder of the published app under _content/{PACKAGE ID}/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
when examining the wwwroot
folder for the published assets.
Additional resources
Razor views, pages, controllers, page models, Razor components, View components, and data models can be built into a Razor class library (RCL). The RCL can be packaged and reused. Applications can include the RCL and override the views and pages it contains. When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence.
View or download sample code (how to download)
Create a class library containing Razor UI
- From the Visual Studio File menu, select New > Project.
- Select ASP.NET Core Web Application.
- Name the library (for example, "RazorClassLib") > OK. To avoid a file name collision with the generated view library, ensure the library name doesn't end in
.Views
. - Verify ASP.NET Core 2.1 or later is selected.
- Select Razor Class Library > OK.
An RCL has the following project file:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
Add Razor files to the RCL.
The ASP.NET Core templates assume the RCL content is in the Areas
folder. See RCL Pages layout to create an RCL that exposes content in ~/Pages
rather than ~/Areas/Pages
.
Reference RCL content
The RCL can be referenced by:
- NuGet package. See Creating NuGet packages and dotnet add package and Create and publish a NuGet package.
{ProjectName}.csproj
. See dotnet-add reference.
Walkthrough: Create an RCL project and use from a Razor Pages project
You can download the complete project and test it rather than creating it. The sample download contains additional code and links that make the project easy to test. You can leave feedback in this GitHub issue with your comments on download samples versus step-by-step instructions.
Test the download app
If you haven't downloaded the completed app and would rather create the walkthrough project, skip to the next section.
Open the .sln
file in Visual Studio. Run the app.
Follow the instructions in Test WebApp1
Create an RCL
In this section, an RCL is created. Razor files are added to the RCL.
Create the RCL project:
- From the Visual Studio File menu, select New > Project.
- Select ASP.NET Core Web Application.
- Name the app RazorUIClassLib > OK.
- Verify ASP.NET Core 2.1 or later is selected.
- Select Razor Class Library > OK.
- Add a Razor partial view file named
RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
.
Add Razor files and folders to the project
Replace the markup in
RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
with the following code:<h3>_Message.cshtml partial view.</h3> <p>RazorUIClassLib\Areas\MyFeature\Pages\Shared\_Message.cshtml</p>
Replace the markup in
RazorUIClassLib/Areas/MyFeature/Pages/Page1.cshtml
with the following code:@page @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <h2>Hello from a Razor UI class library!</h2> <p> From RazorUIClassLib\Areas\MyFeature\Pages\Page1.cshtml</p> <partial name="_Message" />
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
is required to use the partial view (<partial name="_Message" />
). Rather than including the@addTagHelper
directive, you can add a_ViewImports.cshtml
file. For example:dotnet new viewimports -o RazorUIClassLib/Areas/MyFeature/Pages
For more information on
_ViewImports.cshtml
, see Importing Shared DirectivesBuild the class library to verify there are no compiler errors:
dotnet build RazorUIClassLib
The build output contains RazorUIClassLib.dll
and RazorUIClassLib.Views.dll
. RazorUIClassLib.Views.dll
contains the compiled Razor content.
Use the Razor UI library from a Razor Pages project
Create the Razor Pages web app:
From Solution Explorer, right-click the solution > Add > New Project.
Select ASP.NET Core Web Application.
Name the app WebApp1.
Verify ASP.NET Core 2.1 or later is selected.
Select Web Application > OK.
From Solution Explorer, right-click on WebApp1 and select Set as StartUp Project.
From Solution Explorer, right-click on WebApp1 and select Build Dependencies > Project Dependencies.
Check RazorUIClassLib as a dependency of WebApp1.
From Solution Explorer, right-click on WebApp1 and select Add > Reference.
In the Reference Manager dialog, check RazorUIClassLib > OK.
Run the app.
Test WebApp1
Browse to /MyFeature/Page1
to verify that the Razor UI class library is in use.
Override views, partial views, and pages
When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence. For example, add WebApp1/Areas/MyFeature/Pages/Page1.cshtml
to WebApp1, and Page1 in the WebApp1 will take precedence over Page1 in the RCL.
In the sample download, rename WebApp1/Areas/MyFeature2
to WebApp1/Areas/MyFeature
to test precedence.
Copy the RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
partial view to WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml
. Update the markup to indicate the new location. Build and run the app to verify the app's version of the partial is being used.
RCL Pages layout
To reference RCL content as though it is part of the web app's Pages
folder, create the RCL project with the following file structure:
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
Suppose RazorUIClassLib/Pages/Shared
contains two partial files: _Header.cshtml
and _Footer.cshtml
. The <partial>
tags could be added to _Layout.cshtml
file:
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
Razor views, pages, controllers, page models, Razor components, View components, and data models can be built into a Razor class library (RCL). The RCL can be packaged and reused. Applications can include the RCL and override the views and pages it contains. When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence.
View or download sample code (how to download)
Create a class library containing Razor UI
- From Visual Studio select Create new a new project.
- Select Razor Class Library > Next.
- Name the library (for example, "RazorClassLib"), > Create. To avoid a file name collision with the generated view library, ensure the library name doesn't end in
.Views
. - Select Support pages and views if you need to support views. By default, only Razor Pages are supported. Select Create.
The Razor class library (RCL) template defaults to Razor component development by default. The Support pages and views option supports pages and views.
Add Razor files to the RCL.
The ASP.NET Core templates assume the RCL content is in the Areas
folder. See RCL Pages layout below to create an RCL that exposes content in ~/Pages
rather than ~/Areas/Pages
.
Reference RCL content
The RCL can be referenced by:
- NuGet package. See Creating NuGet packages and dotnet add package and Create and publish a NuGet package.
{ProjectName}.csproj
. See dotnet-add reference.
Override views, partial views, and pages
When a view, partial view, or Razor Page is found in both the web app and the RCL, the Razor markup (.cshtml
file) in the web app takes precedence. For example, add WebApp1/Areas/MyFeature/Pages/Page1.cshtml
to WebApp1, and Page1 in the WebApp1 will take precedence over Page1 in the RCL.
In the sample download, rename WebApp1/Areas/MyFeature2
to WebApp1/Areas/MyFeature
to test precedence.
Copy the RazorUIClassLib/Areas/MyFeature/Pages/Shared/_Message.cshtml
partial view to WebApp1/Areas/MyFeature/Pages/Shared/_Message.cshtml
. Update the markup to indicate the new location. Build and run the app to verify the app's version of the partial is being used.
If the RCL uses Razor Pages, enable the Razor Pages services and endpoints in the hosting app:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
RCL Pages layout
To reference RCL content as though it is part of the web app's Pages
folder, create the RCL project with the following file structure:
RazorUIClassLib/Pages
RazorUIClassLib/Pages/Shared
Suppose RazorUIClassLib/Pages/Shared
contains two partial files: _Header.cshtml
and _Footer.cshtml
. The <partial>
tags could be added to _Layout.cshtml
file:
<body>
<partial name="_Header">
@RenderBody()
<partial name="_Footer">
</body>
Add the _ViewStart.cshtml
file to the RCL project's Pages
folder to use the _Layout.cshtml
file from the host web app:
@{
Layout = "_Layout";
}
Create an RCL with static assets
An RCL may require companion static assets that can be referenced by either the RCL or the consuming app of the RCL. ASP.NET Core allows creating RCLs that include static assets that are available to a consuming app.
To include companion assets as part of an RCL, create a wwwroot
folder in the class library and include any required files in that folder.
When packing an RCL, all companion assets in the wwwroot
folder are automatically included in the package.
Use the dotnet pack
command rather than the NuGet.exe version nuget pack
.
Exclude static assets
To exclude static assets, add the desired exclusion path to the $(DefaultItemExcludes)
property group in the project file. Separate entries with a semicolon (;
).
In the following example, the lib.css
stylesheet in the wwwroot
folder isn't considered a static asset and isn't included in the published RCL:
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);wwwroot\lib.css</DefaultItemExcludes>
</PropertyGroup>
Typescript integration
To include TypeScript files in an RCL:
Reference the
Microsoft.TypeScript.MSBuild
NuGet package in the project.Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Place the TypeScript files (
.ts
) outside of thewwwroot
folder. For example, place the files in aClient
folder.Configure the TypeScript build output for the
wwwroot
folder. Set theTypescriptOutDir
property inside of aPropertyGroup
in the project file:<TypescriptOutDir>wwwroot</TypescriptOutDir>
Include the TypeScript target as a dependency of the
ResolveCurrentProjectStaticWebAssets
target by adding the following target inside of aPropertyGroup
in the project file:<ResolveCurrentProjectStaticWebAssetsInputsDependsOn> CompileTypeScript; $(ResolveCurrentProjectStaticWebAssetsInputs) </ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
Consume content from a referenced RCL
The files included in the wwwroot
folder of the RCL are exposed to either the RCL or the consuming app under the prefix _content/{PACKAGE ID}/
. For example, a library with an assembly name of Razor.Class.Lib
and without a <PackageId>
specified in its project file results in a path to static content at _content/Razor.Class.Lib/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
.
The consuming app references static assets provided by the library with <script>
, <style>
, <img>
, and other HTML tags. The consuming app must have static file support enabled in Startup.Configure
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseStaticFiles();
...
}
When running the consuming app from build output (dotnet run
), static web assets are enabled by default in the Development environment. To support assets in other environments when running from build output, call UseStaticWebAssets
on the host builder in Program.cs
:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStaticWebAssets();
webBuilder.UseStartup<Startup>();
});
}
Calling UseStaticWebAssets
isn't required when running an app from published output (dotnet publish
).
Multi-project development flow
When the consuming app runs:
- The assets in the RCL stay in their original folders. The assets aren't moved to the consuming app.
- Any change within the RCL's
wwwroot
folder is reflected in the consuming app after the RCL is rebuilt and without rebuilding the consuming app.
When the RCL is built, a manifest is produced that describes the static web asset locations. The consuming app reads the manifest at runtime to consume the assets from referenced projects and packages. When a new asset is added to an RCL, the RCL must be rebuilt to update its manifest before a consuming app can access the new asset.
Publish
When the app is published, the companion assets from all referenced projects and packages are copied into the wwwroot
folder of the published app under _content/{PACKAGE ID}/
. When producing a NuGet package and the assembly name isn't the same as the package ID (<PackageId>
in the library's project file), use the package ID as specified in the project file for {PACKAGE ID}
when examining the wwwroot
folder for the published assets.