Solution:
As mentioned by @Zhi Lv I had to clear the cache.
Instead of clearing the cache of all packages I choose to go manually to C:\Users\<username>\.nuget\packages\
and delete the folder containing my package (in this case the folder named: RazorClassLibraryTest
).
Problem:
So I'm experimenting with creating NuGet packages and this one has a tag helper and an extension method for the IApplicationBuilder
, I packed the package and put it in a local folder, added the folder to the packages sources then installed the package.
Package project structure:
TagHelperNuGet/
├── wwwroot/
│ ├── css/
│ │ └── style.cs
│ └── js/
│ └── script.js
├── TagHelpers/
│ └── BtnTagHelper.cs
└── Extensions/
└── StaticFileExtension.cs
The tag helper get recognized (after adding @addTagHelper *, RazorClassLibraryTest
ofc), but the extension method does not.
When I try importing the name space in my Program.cs
file
using RazorClassLibraryTest.Extensions;
I get
The type or namespace name 'Extensions' does not exist in the namespace 'RazorClassLibraryTest' (are you missing an assembly reference?)
But when I do the same for the tag helper name space, it get imported with out any problems
using RazorClassLibraryTest.TagHelpers;
This is the code of both files:
AlertBtnTagHleper.cs
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace RazorClassLibraryTest.TagHelpers
{
[HtmlTargetElement("alert-btn")]
public class AlertBtnTagHelper : TagHelper
{
[HtmlAttributeName("text")]
public string Text { get; set; } = "Show Alert";
[HtmlAttributeName("message")]
public string Message { get; set; } = "Hello World!";
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "button";
output.Attributes.SetAttribute("type", "button");
output.Attributes.SetAttribute("class", "btn-alert");
output.Attributes.SetAttribute("onclick", $"showAlert('{Message}')");
output.Content.SetContent(Text);
}
}
}
StaticFilesExtention.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using System.Reflection;
namespace RazorClassLibraryTest.Extensions
{
public static class StaticFilesExtension
{
/// <summary>
/// Configures the application to serve static files from a specified staticFilesRoot path.
/// </summary>
/// <param name="app">The application builder.</param>
/// <param name="staticFilesRoot">The staticFilesRoot path to serve static files from. Defaults to <c>_content/RazorClassLibraryTest/</c>.</param>
/// <returns>The application builder.</returns>
public static IApplicationBuilder UseTagStatics(this IApplicationBuilder app, string? staticFilesRoot)
{
if (string.IsNullOrWhiteSpace(staticFilesRoot))
return app;
app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments(staticFilesRoot))
{
Assembly assembly = Assembly.GetAssembly(typeof(StaticFilesExtension))!;
string? assemblyName = assembly.GetName().Name;
if (string.IsNullOrWhiteSpace(assemblyName))
throw new InvalidOperationException("The assembly name could not be determined.");
string assetPath = context.Request.Path.Value[(staticFilesRoot.Length + 1)..];
context.Request.Path = $"/_content/{assemblyName}/{assetPath}";
}
await next();
});
return app;
}
/// <summary>
/// Configures the application to serve static files from a path specified in the configuration.
/// </summary>
/// <param name="app">The application builder.</param>
/// <param name="configuration">The configuration to get the staticFilesRoot path from. Expects the value to be stored in "RazorTag.StaticFilesRoot".</param>
/// <returns>The application builder.</returns>
public static IApplicationBuilder UseTagStatics(this IApplicationBuilder app, IConfiguration configuration)
{
string? configStaticFilesRoot = configuration["RazorTag:StaticFilesRoot"];
if (string.IsNullOrWhiteSpace(configStaticFilesRoot))
return app;
return app.UseTagStatics(configStaticFilesRoot);
}
}
}
Code review and improvement advices are welcome, and thank you.
Edit:
The Extensions are packaged but they still doesn't work Image of the package structure using DotPeek application
Edit2:
The code from .csproj
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
</ItemGroup>
</Project>
Since you enabled GeneratePackageOnBuild
, when build the application, by default it will generate a .nupkg file in the {project folder}/bin/Debug folder
. So might be the issue relate the generate file, it is not the latest version.
Try to open the project folder and delete the bin folder and then rebuild the application and get the latest version.
Then you can try to refer the following steps to install the Nuget package from local source.
Right click your project, select "Manange NuGet Package..." option.
In the NeGet panel, click the Settings icon, in the popup window, click add button to create a new package source, set the Name and set the source to the path of your local folder ({your project folder/bin/Debug}).
Then change the Package Source, you can find the local .nupkg package and then you can install it in your application.
After that you can use the relate classes. You can have a try.
Update:
After install the nuget package from local package source, we can find the package from here:
Then, use the StaticFilesExtension:
To use the custom TagHelper, I can add the namespace reference in the _ViewImports.cshtml and then use the custom tag.
As we can see, we can use both of them.
When I test your code, I meet a showAlert
not defined error, after I change the showAlert
to alert
in class library, it continues display the showAlert
not defined error. The cause of this problem is that we didn't update the package, which might be similar to your issue. So, in my previous reply, I suggest you delete the bin folder and re-generate the package and then installed the latest package.
Besides, the NuGet cache might prevent us to install the updated package, you can try to clear the NuGet cache (use the Tools > NuGet Package Manager > Package Manager Settings menu command, then select Clear All NuGet Cache(s) and re-install the package.