6

问题

是否可以使用没有预编译的 Web 部署项目发布 Web 应用程序项目?

笔记

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

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

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

[更新]

我正在考虑自定义 Microsoft.WebDeployment.targets 文件以完成此操作,但到目前为止我还没有运气。

[更新]

在挖掘 Microsoft.WebDeployment.targets 文件时,我发现没有直接的方法可以将 Web 部署项目与 Web 应用程序预编译分离。事实上,我不确定有没有必要。我现在使用的是类似于以下代码段的东西。我只是将其放入项目文件中,并带有一个条件 attr 以不部署用于调试构建。

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

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

4

3 回答 3

2

要使 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 的内容。

于 2011-05-26T21:51:19.053 回答
1

也许我遗漏了一些东西(我对 VirtualPathProviders 没有任何经验),但是如果您只是希望您的 aspx 和 ascx 文件不被预编译,请在编译部分中勾选“允许此预编译站点可更新”框部署项目的属性页(对于您使用的任何配置)。

来自MSDN

允许此预编译站点可更新

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

于 2009-08-11T01:09:38.237 回答
0

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

希望这可以帮助。

于 2009-08-11T20:53:08.530 回答