MVC:未创建在'〜/.../ Index.cshtml'中找到的视图

时间:2013-12-16 15:02:30

标签: c# asp.net-mvc razor

我创建了一个模块化MVC项目,用于在同一运行时加载其他特殊Web项目。

其他项目位于名为“模块”的网站根目录下的文件夹中。 我正在使用 PreApplicationStartMethod 属性在启动时加载子目录中的其他程序集。

我添加了特殊路由来定位具有命名空间约束的每个模块。

我创建了一个实现 RazorViewEngine 的类,当对模块中的元素进行调用时,它会覆盖 viewPath :〜/ Views / Home / Index.cshtml - > 〜/模块/ ModuleTest /查看/主页/ Index.cshtml。

动态加载的库中的 Index()方法已成功调用,但在呈现视图时出错:

见下图:http://i.imgur.com/KoTgxg2.png

框架告诉我基本上已找到视图,但他不会渲染它。 有谁知道为什么框架拒绝渲染它?

应用程序中的服务器错误。

未在'〜/ Modules / ModuleTest / Views / Home / Index.cshtml'中找到视图。

描述:执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.InvalidOperationException:未创建在'〜/ Modules / ModuleTest / Views / Home / Index.cshtml'中找到的视图。

  • 异常
Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 

[InvalidOperationException: The view found at '~/Modules/ModuleTest/Views/Home/Index.cshtml' was not created.]
   System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +362
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +431
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +39
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +116
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +529
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +106
   System.Web.Mvc.Async.c__DisplayClass28.b__19() +321
   System.Web.Mvc.Async.c__DisplayClass1e.b__1b(IAsyncResult asyncResult) +185
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +133
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40
   System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44
   System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +39
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +62
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39
   System.Web.Mvc.MvcHandler.b__4(IAsyncResult asyncResult, ProcessRequestState innerState) +39
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9514812
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18408
  • 控制器

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
           return View(new TestModel() { Value = "Bla" });
        }
    }
  • 查看

    @using Easily.ModuleTest.Models;
    @{ ViewBag.Title = "Test Index"; }
    @model TestModel
    @Model.Value

  • CustomRazorViewEngine

    public class CustomRazorViewEngine : RazorViewEngine
    {
        public CustomRazorViewEngine()
        {
            List tmpViewLocationFormats = new List(ViewLocationFormats);
            List tmpMasterLocationFormats = new List(MasterLocationFormats);
            List tmpPartialViewLocationFormats = new List(PartialViewLocationFormats);
            foreach (string moduleDirectory in EasilyModulesContainer.Modules.Select(x => x.Directory))
            {
                foreach (string viewLocationFormat in ViewLocationFormats)
                    tmpViewLocationFormats.Add(viewLocationFormat.Replace("~/", string.Format("~/{0}/{1}/", Constants.ModulesDirectory, moduleDirectory)));
                foreach (string masterLocationFormat in MasterLocationFormats)
                    tmpMasterLocationFormats.Add(masterLocationFormat.Replace("~/", string.Format("~/{0}/{1}/", Constants.ModulesDirectory, moduleDirectory)));
                foreach (string partialViewLocationFormat in PartialViewLocationFormats)
                    tmpPartialViewLocationFormats.Add(partialViewLocationFormat.Replace("~/", string.Format("~/{0}/{1}/", Constants.ModulesDirectory, moduleDirectory)));
            }
            ViewLocationFormats = tmpViewLocationFormats.ToArray();
            MasterLocationFormats = tmpMasterLocationFormats.ToArray();
            PartialViewLocationFormats = tmpPartialViewLocationFormats.ToArray();
        }

        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return base.CreateView(controllerContext, GetPath(controllerContext, viewPath), masterPath);
        }

        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return base.CreatePartialView(controllerContext, GetPath(controllerContext, partialPath));
        }

        private string GetPath(ControllerContext controllerContext, string path)
        {
            if (!controllerContext.RouteData.Values.ContainsKey("_module"))
                return path;
            Module module = ModulesContainer.Modules.SingleOrDefault(x => x.Name == controllerContext.RouteData.GetRequiredString("_module"));
            return path.Replace("~/", string.Format("~/{0}/{1}/", Constants.ModulesDirectory, module.Directory));
        }
    }

2 个答案:

答案 0 :(得分:8)

我通过调试http://aspnetwebstack.codeplex.com/找到了问题。

我实际上加载了包含来自 ModulesContainer 类中bin的另一个文件夹中的控制器的库(请参阅问题)。但是在 System.Web.Mvc.dll 里面,一个方法尝试通过在默认目录中执行 Assembly.Load()来查找我的控制器类型,其原因为 BuildManager.GetCompiledType()返回 null

我找到了一种简单的方法来覆盖此方法:

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;

private static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (args.RequestingAssembly != null)
            return args.RequestingAssembly;
        Module module = _modules.SingleOrDefault(x => x.Assembly.FullName == args.Name);
        if (module != null)
            return module.Assembly;
        throw new Exception(string.Format("Unable to load assembly {0}", args.Name));
    }

我只是在我的预构建的 dll缓存中查找已经加载的程序集。

答案 1 :(得分:0)

@ Lex2193:我在你的回答中发现了问题。 当我使用你的代码时它运行良好,除了情况,其中引用的程序集有另一个参考依赖:

Module [M] => Dependency [D] => DeepDependency [DD]

当您使用[D]中的模块对象时,会在[DD]中调用某些内容。它将在TypeLoad异常上失败。因为要求组装。 所以我编辑了第一次搜索模块的代码:

public static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
{
    Assembly module = modules.SingleOrDefault(x => x.FullName == args.Name);
    if (module != null)
        return module;

    if (args.RequestingAssembly != null)
        return args.RequestingAssembly;

    throw new Exception(string.Format("Could not load file or assembly {0}", args.Name));
}