简体   繁体   中英

How to render a control in MVC 3 Razor using MEF

First here is my error: The type or namespace name 'Web' could not be found (are you missing a using directive or an assembly reference?)

public class _Page_Plugins_Views_Web_Plugins_Controls_Controls_Menu_cshtml : System.Web.Mvc.WebViewPage<Web.Plugins.Controls.Models.MenuModel> {

I am building a pluggable MVC 3.0 Razor website using MEF and strongly-typed views. I am getting the plugins to work just fine until I get to the building of the menu. The Menu is a plugin of its own. I have used http://www.thegecko.org/index.php/2010/06/pluggable-mvc-2-0-using-mef-and-strongly-typed-views/comment-page-1/#comment-7130 . So far all is well like I mentioned but when I go to render the menu in the layout it pops an error (see it above).

Below is the code that gets this going. Why is it trying to render a view and not just the partial?

My Controller:

[HandleError]
[ControllerMetaData("Controls")]
[Export(typeof(IController)), PartCreationPolicy(CreationPolicy.NonShared)]
public class ControlsController : MefController
{
    public virtual ActionResult Menu()
    {
        var builder = new MenuModelBuilder(Context.MenuContainer);
        ViewData.Model = builder.BuildModel();

        return PartialView();
    }

}

My _Layout.cshtml

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Web.Plugins.Presentation/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/Web.Plugins.Presentation/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Web.Plugins.Presentation/modernizr-1.7.min.js")" type="text/javascript"></script>
</head>
<body>
<div class="page">
    <header>
        <div id="title">
            <h1>My MVC Application</h1>
        </div>
        <div id="logindisplay">
            @Html.Partial("_LogOnPartial")
        </div>
        <nav>
            <ul id="menu">
                @*<li>@Html.ActionLink("Home", "Index", "Home")</li>
                <li>@Html.ActionLink("About", "About", "Home")</li>*@


                @{
                    Html.Action("Menu", "Controls");
                }
            </ul>
        </nav>
    </header>
    <section id="main">
        @RenderBody()
    </section>
    <footer>
    </footer>
</div>

My MefViewEngine.cs

public class MefViewEngine : RazorViewEngine
{
    private readonly string _defaultMaster;

    public MefViewEngine(string pluginPath, IEnumerable<IPluginRegistration> plugins, string defaultMaster)
    {
        _defaultMaster = defaultMaster;
        CreateViewLocations(pluginPath, plugins);
    }

    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
        // Set default master page
        if (string.IsNullOrWhiteSpace(masterName) && !controllerContext.IsChildAction)
        {
            masterName = _defaultMaster;
        }

        // Ensure name is correct
        if (masterName.ToLowerInvariant().EndsWith(".cshtml"))
        {
            masterName = masterName.ToLowerInvariant().Replace(".cshtml", string.Empty);
        }

        if (string.IsNullOrWhiteSpace(masterName))
        {
            return base.FindPartialView(controllerContext, viewName, useCache);
            //masterName = _defaultMaster;
        }
        return base.FindView(controllerContext, viewName, masterName, useCache);
    }

    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
    {
        // If view isn't .aspx, remove master page
        if (!viewPath.ToLowerInvariant().EndsWith(".cshtml"))
        {
            masterPath = string.Empty;
        }

        var nameSpace = controllerContext.Controller.GetType().Namespace;
        //return base.CreateView(controllerContext, viewPath.Replace("%1", nameSpace), masterPath.Replace("%1", nameSpace));

        return base.CreateView(controllerContext, viewPath, masterPath);
    }

    #region Helper Methods

    private void CreateViewLocations(string pluginPath, IEnumerable<IPluginRegistration> plugins)
    {
        IList<string> viewLocations = new List<string>();
        IList<string> masterLocations = new List<string>();
        string pluginLocation;

        foreach (IPluginRegistration plugin in plugins)
        {
            pluginLocation = string.Format("~/{0}/Views/{1}/", pluginPath, plugin.AssemblyName);
            AddViewLocation(viewLocations, pluginLocation);
            AddMasterLocation(masterLocations, pluginLocation);
        }

        pluginLocation = "~/Views/";
        AddViewLocation(viewLocations, pluginLocation);

        ViewLocationFormats = viewLocations.ToArray();
        PartialViewLocationFormats = viewLocations.ToArray();
        MasterLocationFormats = masterLocations.ToArray();

        AreaViewLocationFormats = new[] {
            "~/" + pluginPath + "/Views/{2}/{1}/{0}.cshtml",
            "~/" + pluginPath + "/Views/{2}/{1}/{0}.cshtml",
            "~/" + pluginPath + "/Views/{2}/Shared/{0}.cshtml",
            "~/" + pluginPath + "/Views/{2}/Shared/{0}.cshtml",
        };

        AreaPartialViewLocationFormats = AreaViewLocationFormats;

        AreaMasterLocationFormats = new[] {
            "~/" + pluginPath + "/Views/{2}/{1}/{0}.cshtml",
            "~/" + pluginPath + "/Views/{2}/Shared/{0}.cshtml",
        };
    }

    private static void AddViewLocation(IList<string> viewLocations, string pluginLocation)
    {
        viewLocations.Add(pluginLocation + "{1}/{0}.cshtml");
        viewLocations.Add(pluginLocation + "{1}/{0}.cshtml");
        viewLocations.Add(pluginLocation + "Shared/{0}.cshtml");
        viewLocations.Add(pluginLocation + "Controls/{0}.cshtml");
        viewLocations.Add(pluginLocation + "Shared/{0}.cshtml");
    }

    private static void AddMasterLocation(IList<string> viewLocations, string pluginLocation)
    {
        viewLocations.Add(pluginLocation + "{0}.cshtml");
        viewLocations.Add(pluginLocation + "{1}/{0}.cshtml");
        viewLocations.Add(pluginLocation + "Shared/{0}.cshtml");
    }

    #endregion
}

Have you added all of your namespaces to the web.config in the Views folder? You should also add the same references to the web.config files in your Areas, if any.

Any namespaces you create and reference in your Razor views must be added to the namespace collection contained in the element.

I don't know about MEF but from the little I know about MVC, shouldn't you be returning a PartialViewResult rather than an Action result?

public virtual PartialViewResult Menu()
{
    var builder = new MenuModelBuilder(Context.MenuContainer);
    ViewData.Model = builder.BuildModel();

    return PartialView();
}

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