【问题标题】:NotSupportedException in Asp.NET Core MVC Razor Pages RenderingAsp.NET Core MVC Razor 页面渲染中的 NotSupportedException
【发布时间】:2019-08-26 10:48:55
【问题描述】:

我最近创建了一个小型 ASP.Net Core MVC 项目,并将所有 .cshtml 文件放在 Views 目录中。然后我在 Startup.cs 中使用以下代码来更改 Razor 搜索视图文件的位置:

services.Configure<RazorViewEngineOptions>(options => {
    //{2} is area, {1} is controller, {0} is the action    
    options.ViewLocationFormats.Clear();
    options.ViewLocationFormats.Add("/Views/{1}" + RazorViewEngine.ViewExtension);
});

.cshtml 文件映射到相应的控制器名称,其中所有控制器都包含一个默认的“索引”操作,该操作仅返回关联的 View()。

这是当前路由:

app.UseMvc(routes => {
    routes.MapRoute(
        name: "default",
        template: "{controller=Index}/{action=Index}/{id?}");
});

在我看来,这个配置应该可以工作,但是每当我尝试调用任何页面时,Razor 都会抛出“NotSupportedException”,我不确定如何调试它:

NotSupportedException: Specified method is not supported.
Microsoft.AspNetCore.Mvc.RazorPages.PageBase.EnsureRenderedBodyOrSections()
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(ViewContext context, ViewBufferTextWriter bodyWriter)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync<TFilter, TFilterAsync>()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我查看了 EnsureRenderedBodyOrSections() 的源码,简单如下:

public override void EnsureRenderedBodyOrSections() {
    //This will never be called by MVC. MVC only calls this method on layout pages, and a Page can never be a layout page.
    throw new NotSupportedException();
}

MVC 显然在不应该调用该函数时调用了该函数。这里究竟存在什么问题?

PS:这是GitHub上的项目:https://github.com/mathusummut/nemesys-stackoverflow

【问题讨论】:

  • 那么您有一个名为 Index 的控制器? template: "{controller=Index} 在你的路由中?
  • 是的,它是为了显示主页是Index.cshtml。
  • 是的。一个 github 链接可能会有所帮助。
  • 您似乎正在尝试将 Razor 页面用作 MVC 应用程序的视图。如果您从Controller 返回View(...) 结果,则不应将页面用于视图。 Page 是一个 .cshtml 文件,顶部带有 @page 指令。这些技术对于给定的请求路径是互斥的。您可以在同一个应用程序中同时使用它们,但不能在同一个请求中使用它们。我建议从您的视图中删除 @page 指令并从那里开始。
  • 我现在把它写成一个:)

标签: c# asp.net-core asp.net-core-mvc razor-pages


【解决方案1】:

之所以调用EnsureRenderedBodyOrSections 方法是因为您从控制器返回View() 结果,并且此方法是视图 渲染生命周期的一部分。但是,您的 Razor 文件在顶部有 @page 指令,这使它们成为 Razor Pages 的页面文件。

虽然您可以在同一个应用程序中使用 MVC 视图和 Razor 页面,但它们不能混合用于一个请求路径。如果您从视图文件中删除 @page 指令,它们将被编译为 Razor 视图而不是 Razor 页面,因此您不会得到 NotSupportedException。

作为旁注,我建议删除options.ViewLocationFormats.Clear(); 行并保留默认视图位置,以便您将来可以使用Views/{Controller}/{Action} 视图位置,同时仍然能够拥有一个名为@987654328 的视图文件@。这样,当您向现在的 MVC 应用程序添加更多功能时,您可以使用传统的 MVC 模式来实现。

【讨论】:

  • 谢谢!我确实听取了您对选项的建议,现在改为 options.ViewLocationFormats.Insert(0, "/Views/{1}" + RazorViewEngine.ViewExtension);
猜你喜欢
  • 2020-08-22
  • 2019-08-04
  • 2021-05-13
  • 2018-06-15
  • 2012-05-28
  • 2011-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多