简体   繁体   中英

NotSupportedException in Asp.NET Core MVC Razor Pages Rendering

I recently created a small ASP.Net Core MVC project, and placed all my .cshtml files in the Views directory. Then I using the following code in Startup.cs to change where Razor searches for the view files:

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

The .cshtml files map to a corresponding controller name, where all controllers contain a default "Index" action that simply returns the associated View().

This is the current routing:

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

In my eyes this configuration should work, however a "NotSupportedException" is being thrown by Razor whenever I try to invoke any page, and I am unsure how to debug this:

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)

I looked at the source code of EnsureRenderedBodyOrSections(), which is simply the following:

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 is apparently calling the function when it's not supposed to. What exactly is the issue that's at play here?

PS: This is the project on GitHub: https://github.com/mathusummut/nemesys-stackoverflow

The reason the EnsureRenderedBodyOrSections method is being called is because you're returning a View() result from a Controller, and this method is part of the rendering lifecycle for Views . Your Razor files, however, have @page directives at the top, which makes them into Page files for Razor Pages .

While you can use MVC Views and Razor Pages in the same application, they cannot be mixed for one request path . If you remove the @page directive from your View files, they will be compiled as Razor Views and not Razor Pages, so you will not get a NotSupportedException .

As a side note, I would recommend removing the line options.ViewLocationFormats.Clear(); and keep the default view location, so that you can use the Views/{Controller}/{Action} view location in the future while still being able to have a view file named Views/{Controller} . That way as you add more functionality to the now-MVC application, you can do so using traditional MVC patterns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM