Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Deployment Project: Publish without Precompilation

The Question

Is it possible to publish a web application project using a web deployment project without precompilation?

Notes

In order to split out web controls and pages into a separate assembly, I am using a custom VirtualPathProvider to load these resources. I am using web deployment projects and msbuild at cmd line to deploy these projects.

The crux of the matter is that VirtualPathProviders are not supported for precompiled applications. I have found a workaround for regular files here. However, this does not work for application files such as ascx and aspx pages. It throws an exception along the lines of "the file has not been pre-compiled, and cannot be requested".

As a result, I have decided to attempt to abandon precompilation altogether and take the initial request performance hit since our site traffic isn't particularly high. However, I can't figure out how to do this using Web Deployment Projects, which are already very baked into our build process.

[update]

I am looking into customizing the Microsoft.WebDeployment.targets file in order to accomplish this, but I haven't had any luck so far.

[update]

In digging around in the Microsoft.WebDeployment.targets file, I have found that there is no straightforward way of decoupling Web Deployment projects from Web Application Precompilation. In fact, I'm not certain there's any need to. What I am now using instead is something akin to the following snippet. I just put it into the project file with a condition attr to not deploy for Debug builds.

<Target Name="AfterBuild">
    <!-- clean output dir -->
    <CreateItem Include="$(output)**\*.*">
        <Output TaskParameter="Include" ItemName="OldFiles"/>
    </CreateItem>
    <Delete ContinueOnError="true"
        TreatErrorsAsWarnings="true" Files="@(OldFiles)"/>
    <!-- copy content -->
    <Copy SourceFiles="@(Content)"
        DestinationFolder="$(output)%(Content.RelativeDir)" />
    <CreateItem Include="$(OutputPath)\*">
        <Output TaskParameter="Include" ItemName="Binaries" />
    </CreateItem>
    <Copy SourceFiles="@(Binaries)" DestinationFolder="$(output)bin" />
    <ReplaceConfigSections RootPath="$(output)"
        WebConfigReplacementFiles="@(ConfigFiles)"
        UseExternalConfigSource="true"
        ValidateSectionElements="true"/>
</Target>

It seems as though this is all that's needed in order to deploy a project without precompilation. Let me know if you find anything better.

like image 610
brad Avatar asked Aug 07 '09 14:08

brad


2 Answers

To make VirtualPathProvider work with precompiled website (or at most partially precompiled), you need to do what Alconja say in conjunction to this http://sunali.com/2008/01/09/virtualpathprovider-in-precompiled-web-sites/

Instead common "AppInitialize":

public static void AppInitialize()
{
    HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider())
}

Use this:

public static void AppInitialize()
{
    HostingEnvironment hostingEnvironmentInstance=(HostingEnvironment)typeof(HostingEnvironment).InvokeMember("_theHostingEnvironment",  BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, null, null, null);

    MethodInfo mi = typeof(HostingEnvironment).GetMethod("RegisterVirtualPathProviderInternal", BindingFlags.NonPublic | BindingFlags.Static);

    mi.Invoke(hostingEnvironmentInstance, new object[] { (VirtualPathProvider)new MyVirtualPathProvider()});
}

According to reference, original action filter precompiled websites. You can achieve what you want intercepting RegisterVirtualPathProviderInternal using reflection, besides normal RegisterVirtualPathProvider method.

like image 143
Breno Mansur Rabelo Avatar answered Sep 16 '22 19:09

Breno Mansur Rabelo


Maybe I'm missing something (I don't have any experience with VirtualPathProviders), but if you just want your aspx & ascx files to not be precompiled ticking the "Allow this precompiled site to be updatable" box in the Compilation section of the deployment project's property pages (for whichever configuration you're using).

From MSDN:

Allow this precompiled site to be updatable

Specifies that the content of .aspx pages are not compiled into an assembly; instead, the markup is left as-is, allowing you to change HTML and client-side functionality after precompiling the Web site. Selecting this check box is equivalent to adding the -u option to the aspnet_compiler.exe command.

like image 43
Alconja Avatar answered Sep 20 '22 19:09

Alconja