I'm building an ASP.NET MVC web application that supports plugins in the form of bundled .dll
files that can contain (among other things) precompiled (through aspnet_compiler.exe
) .aspx
view pages as well as Controller
objects handling requests.
I've built the plugin system so that all plugins are contained within a separate AppDomain
that I create when I instantiate the catalog of plugins. The problem I'm having is that just about everything involving .aspx
requires a web context to work, even if the files themselves are pre-compiled. Even the constructor of a pre-compiled .aspx
file requires a fully setup web context to work (as viewed with Reflector):
public views_home_index_aspx()
{
base.AppRelativeVirtualPath = "~/Views/Home/Index.aspx";
if (!__initialized)
{
string[] virtualFileDependencies = new string[] { "~/Views/Home/Index.aspx", "~/Views/Shared/Module.master" };
__fileDependencies = base.GetWrappedFileDependencies(virtualFileDependencies);
__initialized = true;
}
base.Server.ScriptTimeout = 0x1c9c380;
}
The access to base.Server.ScriptTimeout
at the bottom of the constructor causes initialization of the class to fail because it's done within an self-created AppDomain
that has no web context. As the HttpServerUtility Server { get; }
property is null
, this causes a NullReferenceException
to be thrown.
I've tried wrapping all of the web context requiring logic within the self-started AppDomain
with Phil Haack's HttpSimulator, but that only takes me so far. I get around the access to base.Server
in the constructor, but then make a full stop later when the build manager is trying to access virtual path providers and whatnot to do whatever it's doing to merge the view page with a master page;
System.NullReferenceException: Object reference not set to an instance of an object. at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResult(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean ensureIsUpToDate) at System.Web.UI.MasterPage.CreateMaster(TemplateControl owner, HttpContext context, VirtualPath masterPageFile, IDictionary contentTemplateCollection) at System.Web.UI.Page.ApplyMasterPage() at System.Web.UI.Page.PerformPreInit() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.HandleError(Exception e) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequest(HttpContext context) at System.Web.Mvc.ViewPage.ProcessRequest(HttpContext context) at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.<>c__DisplayClass4.b__3() at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.Wrap[TResult](Func`1 func) at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) at System.Web.Mvc.ViewPage.RenderView(ViewContext viewContext)
So I've basically come to the conclusion that my plugin system won't work since I can't do web context-y stuff within a self-created AppDomain
. I'd love to be proven wrong, though, so please share any solutions to this conundrum you may have.