You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor项目适配Storyblok SDK:无cshtml渲染组件问题求助

解决Storyblok SDK在Blazor项目里没法渲染组件的问题

问题根因

你碰到的问题本质是:这款Storyblok SDK是给Razor Pages设计的,它依赖ASP.NET Core的视图执行器(executor.ExecuteAsync)去查找并渲染.cshtml视图文件,但Blazor用的是.razor组件,两者渲染机制完全不同,所以才会抛出找不到Page视图的异常。

可行修复方案

1. 自定义视图执行器,替换SDK的渲染逻辑

得重写SDK里负责渲染的部分,让它别再找.cshtml视图,改成渲染Blazor组件:

  • 先建一个自定义执行器类,替换SDK默认的视图执行器。这个类要能接收Storyblok返回的数据,解析出要渲染的Blazor组件类型。
  • 用Blazor的RenderComponentAsync方法动态渲染组件,把Storyblok的数据当参数传进去。
  • 修改SDK中间件的逻辑,让它调用你自定义的执行器,而不是原来的executor.ExecuteAsync。

示例代码思路:

// 自定义执行器
public class BlazorComponentExecutor
{
    private readonly IComponentRenderMode _renderMode;
    private readonly IServiceProvider _serviceProvider;

    public BlazorComponentExecutor(IServiceProvider serviceProvider, IComponentRenderMode renderMode)
    {
        _serviceProvider = serviceProvider;
        _renderMode = renderMode;
    }

    public async Task ExecuteAsync(ActionContext actionContext, object storyblokResult)
    {
        // 从storyblokResult里提取组件名称,比如"Page"
        var componentName = ExtractComponentName(storyblokResult);
        // 根据组件名称找到对应的Blazor组件类型
        var componentType = Type.GetType($"你的项目命名空间.Components.{componentName}, 你的项目命名空间");
        
        if (componentType == null)
        {
            throw new InvalidOperationException($"Blazor组件 {componentName} 没找到");
        }

        // 组装组件参数,把Storyblok的数据传进去
        var parameters = new ParameterViewBuilder()
            .Add("StoryData", storyblokResult)
            .Build();

        // 渲染组件并输出到响应
        var httpContext = actionContext.HttpContext;
        var renderer = _serviceProvider.GetRequiredService<IRenderer>();
        var htmlContent = await renderer.RenderComponentAsync(componentType, _renderMode, parameters);
        
        httpContext.Response.ContentType = "text/html";
        await htmlContent.WriteToAsync(httpContext.Response.BodyWriter);
    }

    private string ExtractComponentName(object storyblokResult)
    {
        // 这里根据Storyblok返回的数据结构提取组件名称,比如从story.content.component字段拿
        // 示例:假设storyblokResult是动态对象
        dynamic story = storyblokResult;
        return story.content.component;
    }
}

2. 把SDK输出转成Blazor组件的数据源

要是不想改SDK源码,可以在中间件之后做拦截:

  • 让SDK返回原始的Storyblok数据,别让它尝试渲染视图。
  • 在Blazor的路由页面(比如Pages/StoryblokPage.razor)里,获取SDK返回的数据,然后根据数据动态渲染对应的Blazor组件。

示例Blazor页面:

@page "/storyblok/{slug}"
@inject HttpClient Http

@if (_storyData != null)
{
    @foreach (var component in _storyData.content.components)
    {
        @RenderComponent(component)
    }
}

@code {
    [Parameter]
    public string Slug { get; set; }

    private dynamic _storyData;

    protected override async Task OnInitializedAsync()
    {
        // 调用SDK获取原始数据,这里假设SDK暴露了获取数据的API
        _storyData = await Http.GetFromJsonAsync<dynamic>($"/api/storyblok/{Slug}");
    }

    private RenderFragment RenderComponent(dynamic component)
    {
        return component.component switch
        {
            "Page" => builder =>
            {
                builder.OpenComponent<PageComponent>(0);
                builder.AddAttribute(1, "Data", component);
                builder.CloseComponent();
            },
            "Hero" => builder =>
            {
                builder.OpenComponent<HeroComponent>(0);
                builder.AddAttribute(1, "Data", component);
                builder.CloseComponent();
            },
            // 其他组件映射
            _ => builder => builder.AddContent(0, $"未知组件: {component.component}")
        };
    }
}

3. 查SDK有没有Blazor适配版本

有些开源SDK会有Blazor适配分支,你可以去看该SDK的GitHub仓库,看看有没有Blazor相关的分支、Issue或者PR,有没有其他开发者已经解决了这个问题。要是没有,也可以提个Issue让官方支持Blazor,或者自己写适配代码提交PR。

注意事项

  • Blazor服务器端和WebAssembly端的渲染机制不一样,自定义执行器的时候要区分ServerComponentRenderMode和WebAssemblyComponentRenderMode。
  • 要保证Storyblok返回的组件名称和你的Blazor组件名称对应上,不然还是会找不到组件。

内容的提问来源于stack exchange,提问作者Mike Hagendoorn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:35:38