【问题标题】:Razor engine can't find my view in .Net Core class libraryRazor 引擎在 .Net Core 类库中找不到我的视图
【发布时间】:2017-11-21 18:25:50
【问题描述】:

我有我的类库,其中包含ViewRenderService 类:

public interface IViewRenderService
    {
        Task<string> RenderToStringAsync(string viewName, object model);
    }

    public class ViewRenderService : IViewRenderService
    {
        private readonly IRazorViewEngine _razorViewEngine;
        private readonly ITempDataProvider _tempDataProvider;
        private readonly IServiceProvider _serviceProvider;

        public ViewRenderService(IRazorViewEngine razorViewEngine,
            ITempDataProvider tempDataProvider,
            IServiceProvider serviceProvider)
        {
            _razorViewEngine = razorViewEngine;
            _tempDataProvider = tempDataProvider;
            _serviceProvider = serviceProvider;
        }

        public async Task<string> RenderToStringAsync(string viewName, object model)
        {
            var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            using (var sw = new StringWriter())
            {
                var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);

                if (viewResult.View == null)
                {
                    throw new ArgumentNullException($"{viewName} does not match any available view");
                }

                var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
                {
                    Model = model
                };

                var viewContext = new ViewContext(
                    actionContext,
                    viewResult.View,
                    viewDictionary,
                    new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
                    sw,
                    new HtmlHelperOptions()
                );

                await viewResult.View.RenderAsync(viewContext);
                return sw.ToString();
            }
        }

还有很多视图,从路径开始:my class library root/Views//Shared/many views

问题是,IRazorViewEngine 找不到我的视图,我应该如何调用viewRenderService.RenderToStringAsync(?) 来渲染~/Views/Shared/Myview.cshtml,例如?

【问题讨论】:

    标签: asp.net razor asp.net-core class-library


    【解决方案1】:

    我在类库中处理视图的方式是让视图嵌入资源,即在我拥有的 .csproj 文件中

    <ItemGroup>
      <EmbeddedResource Include="Views\**" Exclude="bin\**;obj\**;**\*.xproj;packages\**;@(EmbeddedResource)" />
    </ItemGroup>
    

    你需要这个包:

    <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="1.1.*" />
    

    然后我的类库中有一个扩展方法,如下所示:

    public static RazorViewEngineOptions AddCloudscribeSimpleContentBootstrap3Views(this RazorViewEngineOptions options)
    {
        options.FileProviders.Add(new EmbeddedFileProvider(
            typeof(Bootstrap3).GetTypeInfo().Assembly,
            "cloudscribe.SimpleContent.Web.Views.Bootstrap3"
        ));
    
        return options;
    }
    

    然后在主应用程序的 Startup.cs 中,您必须选择使用以下扩展方法包含这些视图:

    services.AddMvc()
    .AddRazorOptions(options =>
    {
        options.AddCloudscribeSimpleContentBootstrap3Views();
    });
    

    【讨论】:

    • 谢谢,我试试!
    • 我试过了,还是不行。仍然 viewResult/Views/Myview.cshtml/Views/Shared/Myview.cshtml 中搜索并找不到 Myview.cshtml,但是,我有它/Views/Shared/ 其中razorViewEngine 进行了搜索!
    • 它应该工作,它对我有用。肯定需要重建解决方案以确保它重新编译并包含嵌入文件
    • 看不懂,这行是什么意思:"cloudscribe.SimpleContent.Web.Views.Bootstrap3"?
    • 这是我的类库中包含嵌入式视图的完整程序集名称,您应该将其替换为程序集的名称
    【解决方案2】:

    ASP.NET Core 2.0 更新

    在您的库 .csproj 中,您应该具有以下内容(所有其他提及您的观点的内容都可以删除/评论):

    <Project Sdk="Microsoft.NET.Sdk.Razor">
      <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
      </PropertyGroup>
      <ItemGroup>
        <Content Update="Views\xxx\_MyView.cshtml">
          <Pack>$(IncludeRazorContentInPack)</Pack>
        </Content>
      </ItemGroup>
    </Project>
    

    注意替换Content Includes=Content Update=,这让我很难找到问题所在:)

    以及正确嵌入视图的Project Sdk="Microsoft.NET.Sdk.Razor".Razor

    【讨论】:

    • @JohnZabroski 可能,但你为什么会呢?这里的 lib 仍然兼容 .net 标准,因此可能更轻。只有在需要时才应该这样做,否则只需包含所需的依赖项。
    • 我的意思是像这样使用 TargetFrameworks 属性:&lt;TargetFrameworks&gt;netstandard2.0;netstandard2.1&lt;/TargetFrameworks&gt; - 也许我错过了你关于“仅在需要时才这样做”的观点 - 如果你正在编写库,你无法预料如何将使用这些库,因此 IF 在项目文件写入时无法确定。
    【解决方案3】:

    .Net Core 3.1 更新

    在自己遇到同样的问题挣扎了一段时间后,@Jean 的回答很有帮助。这是我对该答案的 .Net Core 3.1 更新。希望它可以帮助其他人。

    这是在.Net Core 3.1类库的.csproj文件中:

    <Project Sdk="Microsoft.NET.Sdk.Razor">
    
      <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>  
        <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
      </PropertyGroup>
    
      <ItemGroup>
        <Content Update="Views\**\*.cshtml" />
      </ItemGroup>
    
    </Project>
    

    这是库中的文件结构。

    要从 Web 应用程序调用库中的视图组件,请使用:

     @await Component.InvokeAsync("GoogleAnalytics")
    

    【讨论】:

      【解决方案4】:

      我正在复制旧的模板文件并替换内容,并像这样将它们添加到 csproj 中...... 这些并没有在寻找视图时被拾取。

      评论一下就可以了

      <ItemGroup>
          <Content Remove="EmailTemplates\ConfirmEmail.cshtml" />
          <Content Remove="EmailTemplates\ForgotPassword.cshtml" />
         
        </ItemGroup>
      

      【讨论】:

        猜你喜欢
        • 2017-10-15
        • 2014-07-10
        • 2012-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-24
        • 1970-01-01
        相关资源
        最近更新 更多