statiqdev / Statiq.Framework

A flexible and extensible static content generation framework for .NET.
https://statiq.dev/framework
MIT License
418 stars 74 forks source link

Razor Component Support? #194

Open Hecatron opened 3 years ago

Hecatron commented 3 years ago

Hi, I was just wondering, is it possible to render Razor Components (which are normally used with Blazor) within a cshtml file? There is a component Tag helper which you can set to static for rendering, although I couldn't get it to work

I tried adding something like this randomly to the basic example under Statiq.Web

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<component type="typeof(RazorClassLibrary1.Component1)" render-mode="Static" />

but just ended up with a

[ERRO] Archives/PostProcess » ExecuteSwitch » RenderContentPostProcessTemplates » ExecuteIf » ExecuteIf » RenderRazor » [D:/Temp/13/1/Statiq.Web/examples/Statiq.Web.Examples/input/archives/simple-archive.cshtml => archives/simple-archive.html] Invalid URI: The format of the URI could not be determined.
daveaglick commented 2 years ago

In theory Razor component support should be possible since we're using the "official" Razor engine with all the bells and whistles. That said, they're probably enabled via an additional Razor phase that will need to be added.

The error you got is interesting though, I wouldn't have expected to see any error if the component tag helper wasn't available. The fact you're getting some kind of error might mean components are better supported than I would have thought and we just need to track down some other, unrelated error.

In any case, I likely won't have a chance to look into this myself for a while since I'm trying hard to get Statiq Docs out the door. I'll certainly keep the issue open and revisit when I next have a chance to go through the backlog here.

Cryptoc1 commented 1 year ago

Excuse my extreme fashion, I'm quite late.

I've found that this exception occurs when NavigationManager.Initialize is invoked by the StaticComponentRenderer, due to the ViewContext.HttpContext.Request not containing the url data needed to construct the NavigationManager.BaseUri and NavigationManager.Uri.

My workaround of choice was to set the url properties on the HttpContext.Request prior to the ComponentTagHelper's usage (e.g. within _ViewStart.cshtml):

@using Microsoft.AspNetCore.Http

@{
    var url = new Uri( Document.GetLink( true ) );
    HttpContext.Request.Host = new HostString( url.Host );
    HttpContext.Request.Path = url.AbsolutePath;
    HttpContext.Request.Scheme = url.Scheme;
}

NOTE: The Host setting must be set on the Bootstrapper to create an absolute uri (see Linking to Documents).

I believe, ideally, RazorCompiler.GetViewContext could set these properties by default, or, the method be pulled out to an IViewContextFactory service that could be overridden via Bootstrapper.ConfigureServices.

Finally, I've published a Proof of Concept for reference. The PoC also includes a CopyStaticWebAssets module, which reads the underlying manifest file used by the runtime, to copy the Blazor _framework files (as well as all other RCL content) to the output folder.