nuander
nuander

Reputation: 1403

The layout page "~/Views/Shared/" could not be found at the following path

Here's a new twist on this old error. Many of my pages use a layout page so they have this near the top

@{
    Layout = "~/Views/Shared/" + ViewBag.layout;
}

Where viewbag layout is set in an action filter applied to the controller as such

namespace somenamespace.Controllers {
    [SessionSettings]
    public class MyController : Controller {

where the action filter does this

public class SessionSettings : ActionFilterAttribute {
    public override void OnActionExecuting(ActionExecutingContext filterContext) {
        dynamic viewBag = filterContext.Controller.ViewBag;
        string layout = some database lookup
        if (layout == null) layout = "_defaultLayout.cshtml";
        viewBag.layout = layout

and this works pretty well, most of the time. But when I check the Event Logs - Applications - I see Warnings, event ID 1309, event code 3005, "An unhandled exception has occurred" "The layout page "~/Views/Shared/" could not be found at the following path: "~/Views/Shared/"."

And here's the kicker, often event happens on pages that DON'T use the Layouts, they have this at the top

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>...

Anyone have any thoughts on that? Thx

Upvotes: 3

Views: 2817

Answers (1)

Rhumborl
Rhumborl

Reputation: 16609

I traced through the source and found that the issue is with when you set Layout = "~/Views/Shared/" + ViewBag.layout;

When this property is set, the method WebPageExecutingBase.NormalizeLayoutPagePath(string path) is called.

This basically creates an absolute/relative path and then checks if a file exists with that name. Because ViewBag.layout is null, this fails and so errors (you can see the source for this method on codeplex, about halfway down.

It doesn't matter that you later set Layout = null, the _ViewStart code is called first so the error happens.

Your best option I can see is to just check if ViewBag.layout is null before setting it:

if(ViewBag.layout != null)
{
    Layout = "~/Views/Shared/" + ViewBag.layout;
}

I think in this way, you also don't need to explicitly set it to null if they do not have a layout.

Upvotes: 1

Related Questions