Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC : The view found at '~/.../Index.cshtml' was not created

I have created a modular MVC project to load other special web project within the same runtime.

Other projects are located in a folder at the root of the website called "Modules". I am using the attribute PreApplicationStartMethod to load the others assemblies inside the sub directories at boot.

I have added special routes to target each modules with the namespace constraints.

I have create a class who implements RazorViewEngine to override the viewPath when a call is made for the element in the module : ~/Views/Home/Index.cshtml -> ~/Modules/ModuleTest/Views/Home/Index.cshtml.

The Index() method inside the dynamically loaded library is successfully called but i got an error when the view is rendered :

See following image : http://i.imgur.com/KoTgxg2.png

The framework tell me basically that the view has been found but he will not render it. Do anyone has any idea why the framework refuse to render it ?

Server Error in '/' Application.

The view found at '~/Modules/ModuleTest/Views/Home/Index.cshtml' was not created.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The view found at '~/Modules/ModuleTest/Views/Home/Index.cshtml' was not created.

  • Exception
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
  • Controller

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

    @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));
        }
    }
like image 387
Lex2193 Avatar asked Dec 16 '13 15:12

Lex2193


1 Answers

I found the problem by debugging into http://aspnetwebstack.codeplex.com/.

I actually load the library who contain the controllers from another folder than bin in my ModulesContainer class (see question). But inside System.Web.Mvc.dll, one method try to find my controller type by doing a Assembly.Load() in the default directory, its why the BuildManager.GetCompiledType() return null.

I have found a simple way to override this method with :

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;

and

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));
    }

I'm just looking inside my pre-built dll cache to find the already loaded assembly.

like image 131
Lex2193 Avatar answered Oct 20 '22 19:10

Lex2193