我创建了一个模块化的MVC项目来在同一个运行时加载其他特殊的Web项目.
其他项目位于名为"模块"的网站根目录下的文件夹中.我正在使用属性PreApplicationStartMethod 在启动时加载子目录中的其他程序集.
我添加了特殊的路由来定位具有命名空间约束的每个模块.
我创建了一个实现RazorViewEngine的类,当对模块中的元素进行调用时覆盖viewPath:〜/ Views/Home/Index.cshtml - >〜/ Modules/ModuleTest/Views/Home/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)); } }
Lex2193.. 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缓存中查找已经加载的程序集.
我通过调试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缓存中查找已经加载的程序集.