DamianEdwards / RazorSlices

Lightweight Razor-based templates for ASP.NET Core without MVC, Razor Pages, or Blazor.
MIT License
297 stars 12 forks source link

Using RazorSlices in library project #51

Open jtsom opened 4 weeks ago

jtsom commented 4 weeks ago

I have an app that has a separate service library that I need to generate some html. I have the nuget package installed into the project, with the /Slices directory with my .cshtml files and the appropriate _ViewImports.cshtml file(s). After updating to the new version and trying to make the adjustments for the new code, the "slices" don't seem to get generated from the source generator. (I have enabled the output into the /obj directory with <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> in the .csproj, but I don't see any "Generated" files - so I cannot create any slices.

My .cshtml uses partials to pull in several other files, and those were all causing errors. I was previously using RenderPartialAsync("/Slices/_partial.cshtml", model) but an trying to use the new strongly types classes but the new classes aren't found, as the generated files aren't found. Neither are the "top level" files.

My Slices looks like: image

DamianEdwards commented 4 weeks ago

The sample app in the repo includes a Razor class library, as do the benchmark projects, so it's not that it doesn't work at all. I'll need more information to narrow down what's going on here. Can you share an isolated project that reproduces the issue?

DamianEdwards commented 4 weeks ago

Also note it seems common that the editor doesn't see the generated types and shows errors, but the project builds just fine.

jtsom commented 3 weeks ago

I'll try to get some sample - this is an internal app I'm trying to update.

In the simple sample app that I attached to another issue has the generated files in the obj directory, so the source generators are running: image

but in this other solution, the obj directory does not have any of the files that would come from the "slices":

image

jtsom commented 3 weeks ago

I just found this in the solution explorer: image

jtsom commented 3 weeks ago

Here is a sample that attempts to use RazorSlices in a library project. The source generator does not run so the generated files are not there, so cannot create the html.

Net8Test.zip

DamianEdwards commented 3 weeks ago

Your project Net8Test.Service is not using the Razor SDK and thus isn't a Razor Class Library. Once I changed the project file to the following it worked:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

<ItemGroup>
    <PackageReference Include="RazorSlices" Version="0.8.1" />
</ItemGroup>

</Project>

Would be good to add a diagnostic to the Razor Slices source generator that emits a warning if this is detected so it's easier to diagnose.

jtsom commented 3 weeks ago

Yep. That fixes the source generation. But I'm getting this error on build -

image

Nevermind. My error - I had renames the class. Ok now.

Thanks! I'll try this on my original project.

jtsom commented 3 weeks ago

One step forward...

I can't seem to create the Slice - the generated class isn't found:

image

I'd expect to see a "Slices.Hello" in there? and looking at the generated file, I would assume it would be?

image

jtsom commented 3 weeks ago

Again. Nevermind. Closing the solution and reopen it got Visual Studio to wake up.

jtsom commented 3 weeks ago

Now. image

DamianEdwards commented 3 weeks ago

You need to import the RazorSlices namespace to get the extension methods that return a string:

using RazorSlices;

namespace Net8Test.Service;

public class TestService
{
    public async ValueTask<string> Generate(string c)
    {
        var t = new MyTestClass()
        {
            Url = c
        };

        var x = Slices.Hello.Create(t);

        var r = await x.RenderAsync();

        return r;
    }
}

public class MyTestClass
{
    public string Url { get; set; } = null!;
}