Web部署项目:无需预编译即可发布

发布于 2024-08-01 16:18:41 字数 1749 浏览 6 评论 0原文

问题

是否可以使用 Web 部署项目无需预编译来发布 Web 应用程序项目?

为了

将 Web 控件和页面拆分为单独的程序集,我使用自定义 VirtualPathProvider 来加载这些资源。 我正在 cmd 行使用 Web 部署项目和 msbuild 来部署这些项目。

问题的关键是预编译应用程序不支持 VirtualPathProvider。 我在此处找到了常规文件的解决方法。 但是,这不适用于 ascxaspx 页面等应用程序文件。 它抛出“文件尚未预编译,无法请求”的异常。

因此,我决定尝试完全放弃预编译并承受初始请求性能的影响,因为我们的网站流量不是特别高。 但是,我不知道如何使用 Web 部署项目来做到这一点,这些项目已经融入我们的构建过程中。

[update]

我正在考虑自定义 Microsoft.WebDeployment.targets 文件以实现此目的,但到目前为止我还没有任何运气。

[update]

在深入研究 Microsoft.WebDeployment.targets 文件时,我发现没有直接的方法可以将 Web 部署项目与 Web 应用程序预编译解耦。 事实上,我不确定是否有必要这样做。 我现在使用的是类似于以下代码片段的东西。 我只是将其放入项目文件中,并带有一个条件属性,以便不部署调试版本。

<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>

似乎这就是在没有预编译的情况下部署项目所需的全部内容。 如果您发现更好的东西,请告诉我。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一世旳自豪 2024-08-08 16:18:41

要使 VirtualPathProvider 与预编译网站(或最多部分预编译)配合使用,您需要执行 Alconja 结合此 http://sunali.com/2008/01/09/virtualpathprovider-in-precompiled-web-sites/

代替常见的“AppInitialize”:

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

使用这个:

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

根据参考一下,原版动作过滤器预编译网站。 除了普通的 RegisterVirtualPathProvider 方法之外,您还可以使用反射来拦截 RegisterVirtualPathProviderInternal 来实现您想要的目的。

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.

我家小可爱 2024-08-08 16:18:41

也许我错过了一些东西(我没有任何 VirtualPathProviders 的经验),但如果你只想要你的 aspx & 勾选部署项目属性页(无论您使用哪种配置)的编译部分中的“允许此预编译站点可更新”框,以防止预编译 .ascx 文件。

来自 MSDN

允许此预编译站点可更新

指定.aspx页面的内容不被编译成
集会; 相反,标记保持原样,允许您更改
预编译网站后的 HTML 和客户端功能。
选中此复选框相当于将 -u 选项添加到
aspnet_compiler.exe 命令。

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.

指尖上的星空 2024-08-08 16:18:41

我已经成功更新了 ASPX 文件,而无需重新编译,只需在 Visual Studio 中打开各个 ASPX 文件,而无需打开整个项目/解决方案。

希望这可以帮助。

I have had success updating ASPX files without recompiling by simply opening the individual ASPX files in Visual Studio without opening the entire Project/Solution.

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文