我创建了一个模块化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
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));
}
}
答案 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));
}