Visual Studio“作为链接添加”在调试时不工作

时间:2021-09-25 03:04:00

I use Visual Studio 2010 to maintain around 40 different web applications that are all housed on the same website upon deployment. These projects are in the same solution but housed in different projects as they each do very different things.

我使用Visual Studio 2010维护大约40个不同的web应用程序,这些应用程序在部署时都位于同一个网站上。这些项目在相同的解决方案中,但是包含在不同的项目中,因为它们各自做着非常不同的事情。

I'm trying to share css/js files among the various projects via the "Add As Link" option that way I can update the css or js files once and automatically have the updates reflected in the various projects without having to build and redeploy each project.

我正在尝试通过“添加链接”选项在不同的项目*享css/js文件,这样我就可以一次更新css或js文件,并自动在不同的项目中反映更新,而不必构建和重新部署每个项目。

The issue that I am having is when I am trying to run a project locally on my PC for debugging purposes those linked files aren't working. I'm getting a file not found.

我遇到的问题是,当我试图在我的PC上运行一个项目,以调试这些链接文件不能工作的时候。我找不到文件了。

My Thought: I assume that this because the folder structure is different when running the applications locally. I'm curious if there is a way to copy the files to the project only when building in debug mode and adjust the relative URLs accordingly so that I will be able to properly test the application before publishing to our web server.

我的想法是:我认为这是因为在本地运行应用程序时,文件夹结构不同。我很好奇是否只有在调试模式下构建并相应地调整相关url时才有办法将文件复制到项目中,以便在发布到web服务器之前能够正确地测试应用程序。

Thanks,

谢谢,

4 个解决方案

#1


34  

The solution to this problem is copying content files (like js, css or others) which are added as link during each build. There are several ways to do this. I can advice to use MSBuild target which can be reused by different web application projects.

解决这个问题的方法是复制内容文件(如js、css或其他文件),这些文件在每次构建过程中作为链接添加。有几种方法可以做到这一点。我可以建议使用MSBuild目标,它可以被不同的web应用程序项目重用。

So you can create the following file (for example by naming it WebApplication.Extension.targets) with the following content:

因此,您可以使用以下内容创建以下文件(例如,将其命名为WebApplication.Extension.targets):

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <!-- Override the default target dependencies to -->
    <!-- include the new CopyLinkedContentFiles target. -->
    <PropertyGroup>
        <BuildDependsOn>
            CopyLinkedContentFiles;
            $(BuildDependsOn);
        </BuildDependsOn>
    </PropertyGroup>

    <!--
    ============================================================
    CopyLinkedContentFiles

    A new target to copy any linked content files into the 
    web application output folder.

    NOTE: This is necessary even when '$(OutDir)' has not been redirected.
    ============================================================
    -->
    <Target Name="CopyLinkedContentFiles">
        <!-- Remove any old copies of the files -->
        <Delete Condition=" '%(Content.Link)' != '' AND Exists('$(WebProjectOutputDir)\%(Content.Link)') "
                Files="$(WebProjectOutputDir)\%(Content.Link)" />
        <!-- Copy linked content files recursively to the project folder -->
        <Copy Condition=" '%(Content.Link)' != '' " SourceFiles="%(Content.Identity)"
              DestinationFiles="$(WebProjectOutputDir)\%(Content.Link)" />
    </Target>
</Project>

And then add this target to you web application project by placing the following line in .csproj file:

然后,通过在.csproj文件中添加以下行,将此目标添加到您的web应用程序项目中:

<Import Project="$(MSBuildProjectDirectory)[RelativePathToFile]\WebApplication.Extension.targets" />

Basically you can add this line in .csproj file after the following one:

基本上你可以在。csproj文件后添加这一行:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

After this problem with content files added as link should be resolved.

在这个问题之后,添加链接的内容文件应该得到解决。

Edit: To execute the following logic only when debug configuration is built in MSBUILD you have ability to specify Condition element.

编辑:只有在MSBUILD中构建调试配置时,才能执行以下逻辑,您才能指定条件元素。

For example to import specified target only for debug configuration you can update import statement to the following:

例如,要仅为调试配置导入指定的目标,您可以将import语句更新为:

<Import Project="$(MSBuildProjectDirectory)[RelativePathToFile]\WebApplication.Extension.targets" Condition=" '$(Configuration)' == 'Debug' "/>

Edit2:

Edit2:

To overcome this problem some time ago I created a 'MSBuild.WebApplication.CopyContentLinkedFiles' nuget package. This package adds MsBuild target which copies all content files added as link to project folder during build.

为了解决这个问题,不久前我创建了一个MSBuild.WebApplication。CopyContentLinkedFiles nuget包。此包添加MsBuild目标,该目标将在构建期间作为链接添加到项目文件夹的所有内容文件复制。

#2


28  

A solution to automatically copy all linked content files to their "virtual" locations at each build using MSBuild is here:

使用MSBuild自动将所有链接的内容文件复制到每个构建的“虚拟”位置的解决方案如下:

http://mattperdeck.com/post/Copying-linked-content-files-at-each-build-using-MSBuild.aspx

http://mattperdeck.com/post/Copying-linked-content-files-at-each-build-using-MSBuild.aspx

This ensures that your linked files will be available to the browser when you hit F5.

这将确保当您点击F5时,您的链接文件将可用于浏览器。

#3


2  

It can also be solved by pasting the following snippet into the end of your .proj file which will contain the linked files

还可以通过将以下代码片段粘贴到.proj文件的末尾来解决,该文件将包含链接文件

<Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
<Copy SourceFiles="%(Content.Identity)" 
      DestinationFiles="%(Content.Link)" 
      SkipUnchangedFiles='true' 
      OverwriteReadOnlyFiles='true' 
      Condition="'%(Content.Link)' != ''" />

#4


0  

There's one big problem with copying linked files to the virtual location: if you use Go To Definition (Shift + F2) on a JavaScript reference that points to one of the linked files, you'll be taken to the locally-copied file, NOT to the linked file. Then, you're bound to make the mistake of editing the local version, thus eliminating the benefits of using linked files. Additionally, that can cause problems with Intellisense.

将链接文件复制到虚拟位置有一个大问题:如果在指向一个链接文件的JavaScript引用上使用Go定义(Shift + F2),您将被带到本地复制的文件,而不是链接文件。然后,您肯定会犯编辑本地版本的错误,从而消除使用链接文件的好处。此外,这也会导致智能感知的问题。

A better solution: Instead of copying the linked files to the current project directory alongside the associated links, copy them to a "hiddenDebug" folder within that directory (or any directory you wish; keeping it in the same directory makes it easier to manage, and then to manipulate the paths during debug, as I'll explain below).

更好的解决方案:与其将链接文件复制到当前项目目录中,并将它们与相关链接一起,不如将它们复制到该目录(或您希望的任何目录)中的“隐藏bug”文件夹中;将它保存在同一个目录中使它更易于管理,然后在调试期间操作路径,我将在下面解释)。

Here's how to copy the files from your shared repository to your "hiddenDebug" folder (add to your source project's Post-Build event):

以下是如何将文件从共享存储库复制到“隐藏bug”文件夹(添加到源项目的后构建事件中):

Single CSS File

单独的CSS文件中

xcopy /Y "$(ProjectDir)App_Themes\Theme1\Shared.css" "$(SolutionDir)WebApp\App_Themes\Theme1\hiddenDebug\"

选择复制文件/ Y " $()管理扫描App_Themes \ Theme1 \共享。css " " $(SolutionDir)WebApp \ App_Themes \ Theme1 \ hiddenDebug \”

JavaScript directory

JavaScript目录

xcopy /Y /S "$(ProjectDir)Scripts" "$(SolutionDir)WebApp\Scripts\Shared\hiddenDebug\"

xcopy /Y /S "$(ProjectDir)脚本" "$(SolutionDir)WebApp\脚本共享\hiddenDebug\"

When you're debugging, you can dynamically alter the shared files' source paths using Response.Filter in Global.asax. Here's an example:

在调试时,可以使用响应动态地修改共享文件的源路径。在Global.asax过滤器。这里有一个例子:

Response Filter Class (in Shared project)

响应过滤器类(在共享项目中)

Imports System.IO

Namespace Code
    Public Class LinkedReferencesFilter
    Inherits MemoryStream

        Private ReadOnly outputStream As Stream = Nothing
        Private ReadOnly _IsDevEnvironment As Boolean = False

        Public Sub New(ByVal output As Stream, IsDevEnvironment As Boolean)
            Me.outputStream = output
            Me._IsDevEnvironment = IsDevEnvironment
        End Sub

        Public Overrides Sub Write(ByVal buffer As Byte(), ByVal offset As Integer, ByVal count As Integer)
            ' Convert the content in buffer to a string
            Dim contentInBuffer As String = UTF8Encoding.UTF8.GetString(buffer)

            If Me._IsDevEnvironment Then
                contentInBuffer = contentInBuffer.Replace("<script src=""Scripts/Shared/", "<script src=""Scripts/Shared/hiddenDebug/")
                contentInBuffer = contentInBuffer.Replace("/Scripts/Shared/", "/Scripts/Shared/hiddenDebug/")
                contentInBuffer = contentInBuffer.Replace("/App_Themes/Theme1/Shared.css", "/App_Themes/Theme1/hiddenDebug/Shared.css")
            End If

            Me.outputStream.Write(UTF8Encoding.UTF8.GetBytes(contentInBuffer), offset, UTF8Encoding.UTF8.GetByteCount(contentInBuffer))
        End Sub
    End Class
End Namespace

Global.asax

Global.asax

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    ' Simulate internet latency on local browsing
    If Request.IsLocal Then
        System.Threading.Thread.Sleep(50)
    End If

    Dim currentRelativePath As String = Request.AppRelativeCurrentExecutionFilePath

    If request__1.HttpMethod = "GET" Then
        If currentRelativePath.EndsWith(".aspx") Then
            Dim IsDevEnvironment As Boolean = False
            //Use whatever method you want to determine whether your current environment is a development environment:
            #If CONFIG = "Develop" Then
                IsDevEnvironment = True
            #End If

            Response.Filter =
                New Shared.Code.LinkedReferencesFilter(
                    output:=Response.Filter,
                    IsDevEnvironment:=IsDevEnvironment)
        End If
    End If
End Sub

Troubleshooting: Try unloading and reloading the project with linked items. If that doesn't help, add the hiddenDebug directory to your project. I had to do that, but then I was able to remove it later. It's finicky...it would be nice if Microsoft polished this feature, but I'm set for now.

故障排除:尝试卸载和重新加载项目的链接项。如果这没有帮助,请将隐藏bug目录添加到项目中。我必须这么做,但后来我把它删除了。挑剔…如果微软能改进这一功能,那就太好了,但我现在已经准备好了。

In case you didn't know: when you publish your web application, the source (linked) files are automatically copied to the publish target. Once this is set up, you can forget about it. The best part is, you won't lose Intellisense or quick navigation.

如果您不知道:当您发布web应用程序时,源(链接)文件将自动复制到发布目标。设置好之后,您就可以忘记它了。最棒的是,你不会失去智能或快速导航。

After migrating to TypeScript, most JavaScript file reference challenges will be simplified or eliminated (I'm hoping for easy cross-project referencing like what's available for other managed .NET languages, but there may already be some workarounds to enable such functionality).

在迁移到TypeScript之后,大多数JavaScript文件引用的挑战将被简化或消除(我希望可以轻松的跨项目引用,例如其他托管的. net语言可以使用的内容,但是可能已经有一些变通方法来启用这种功能)。

Please let me know whether it works for you, or if you have a better way.

请让我知道它是否对你有用,或者你是否有更好的方法。

#1


34  

The solution to this problem is copying content files (like js, css or others) which are added as link during each build. There are several ways to do this. I can advice to use MSBuild target which can be reused by different web application projects.

解决这个问题的方法是复制内容文件(如js、css或其他文件),这些文件在每次构建过程中作为链接添加。有几种方法可以做到这一点。我可以建议使用MSBuild目标,它可以被不同的web应用程序项目重用。

So you can create the following file (for example by naming it WebApplication.Extension.targets) with the following content:

因此,您可以使用以下内容创建以下文件(例如,将其命名为WebApplication.Extension.targets):

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <!-- Override the default target dependencies to -->
    <!-- include the new CopyLinkedContentFiles target. -->
    <PropertyGroup>
        <BuildDependsOn>
            CopyLinkedContentFiles;
            $(BuildDependsOn);
        </BuildDependsOn>
    </PropertyGroup>

    <!--
    ============================================================
    CopyLinkedContentFiles

    A new target to copy any linked content files into the 
    web application output folder.

    NOTE: This is necessary even when '$(OutDir)' has not been redirected.
    ============================================================
    -->
    <Target Name="CopyLinkedContentFiles">
        <!-- Remove any old copies of the files -->
        <Delete Condition=" '%(Content.Link)' != '' AND Exists('$(WebProjectOutputDir)\%(Content.Link)') "
                Files="$(WebProjectOutputDir)\%(Content.Link)" />
        <!-- Copy linked content files recursively to the project folder -->
        <Copy Condition=" '%(Content.Link)' != '' " SourceFiles="%(Content.Identity)"
              DestinationFiles="$(WebProjectOutputDir)\%(Content.Link)" />
    </Target>
</Project>

And then add this target to you web application project by placing the following line in .csproj file:

然后,通过在.csproj文件中添加以下行,将此目标添加到您的web应用程序项目中:

<Import Project="$(MSBuildProjectDirectory)[RelativePathToFile]\WebApplication.Extension.targets" />

Basically you can add this line in .csproj file after the following one:

基本上你可以在。csproj文件后添加这一行:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

After this problem with content files added as link should be resolved.

在这个问题之后,添加链接的内容文件应该得到解决。

Edit: To execute the following logic only when debug configuration is built in MSBUILD you have ability to specify Condition element.

编辑:只有在MSBUILD中构建调试配置时,才能执行以下逻辑,您才能指定条件元素。

For example to import specified target only for debug configuration you can update import statement to the following:

例如,要仅为调试配置导入指定的目标,您可以将import语句更新为:

<Import Project="$(MSBuildProjectDirectory)[RelativePathToFile]\WebApplication.Extension.targets" Condition=" '$(Configuration)' == 'Debug' "/>

Edit2:

Edit2:

To overcome this problem some time ago I created a 'MSBuild.WebApplication.CopyContentLinkedFiles' nuget package. This package adds MsBuild target which copies all content files added as link to project folder during build.

为了解决这个问题,不久前我创建了一个MSBuild.WebApplication。CopyContentLinkedFiles nuget包。此包添加MsBuild目标,该目标将在构建期间作为链接添加到项目文件夹的所有内容文件复制。

#2


28  

A solution to automatically copy all linked content files to their "virtual" locations at each build using MSBuild is here:

使用MSBuild自动将所有链接的内容文件复制到每个构建的“虚拟”位置的解决方案如下:

http://mattperdeck.com/post/Copying-linked-content-files-at-each-build-using-MSBuild.aspx

http://mattperdeck.com/post/Copying-linked-content-files-at-each-build-using-MSBuild.aspx

This ensures that your linked files will be available to the browser when you hit F5.

这将确保当您点击F5时,您的链接文件将可用于浏览器。

#3


2  

It can also be solved by pasting the following snippet into the end of your .proj file which will contain the linked files

还可以通过将以下代码片段粘贴到.proj文件的末尾来解决,该文件将包含链接文件

<Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
<Copy SourceFiles="%(Content.Identity)" 
      DestinationFiles="%(Content.Link)" 
      SkipUnchangedFiles='true' 
      OverwriteReadOnlyFiles='true' 
      Condition="'%(Content.Link)' != ''" />

#4


0  

There's one big problem with copying linked files to the virtual location: if you use Go To Definition (Shift + F2) on a JavaScript reference that points to one of the linked files, you'll be taken to the locally-copied file, NOT to the linked file. Then, you're bound to make the mistake of editing the local version, thus eliminating the benefits of using linked files. Additionally, that can cause problems with Intellisense.

将链接文件复制到虚拟位置有一个大问题:如果在指向一个链接文件的JavaScript引用上使用Go定义(Shift + F2),您将被带到本地复制的文件,而不是链接文件。然后,您肯定会犯编辑本地版本的错误,从而消除使用链接文件的好处。此外,这也会导致智能感知的问题。

A better solution: Instead of copying the linked files to the current project directory alongside the associated links, copy them to a "hiddenDebug" folder within that directory (or any directory you wish; keeping it in the same directory makes it easier to manage, and then to manipulate the paths during debug, as I'll explain below).

更好的解决方案:与其将链接文件复制到当前项目目录中,并将它们与相关链接一起,不如将它们复制到该目录(或您希望的任何目录)中的“隐藏bug”文件夹中;将它保存在同一个目录中使它更易于管理,然后在调试期间操作路径,我将在下面解释)。

Here's how to copy the files from your shared repository to your "hiddenDebug" folder (add to your source project's Post-Build event):

以下是如何将文件从共享存储库复制到“隐藏bug”文件夹(添加到源项目的后构建事件中):

Single CSS File

单独的CSS文件中

xcopy /Y "$(ProjectDir)App_Themes\Theme1\Shared.css" "$(SolutionDir)WebApp\App_Themes\Theme1\hiddenDebug\"

选择复制文件/ Y " $()管理扫描App_Themes \ Theme1 \共享。css " " $(SolutionDir)WebApp \ App_Themes \ Theme1 \ hiddenDebug \”

JavaScript directory

JavaScript目录

xcopy /Y /S "$(ProjectDir)Scripts" "$(SolutionDir)WebApp\Scripts\Shared\hiddenDebug\"

xcopy /Y /S "$(ProjectDir)脚本" "$(SolutionDir)WebApp\脚本共享\hiddenDebug\"

When you're debugging, you can dynamically alter the shared files' source paths using Response.Filter in Global.asax. Here's an example:

在调试时,可以使用响应动态地修改共享文件的源路径。在Global.asax过滤器。这里有一个例子:

Response Filter Class (in Shared project)

响应过滤器类(在共享项目中)

Imports System.IO

Namespace Code
    Public Class LinkedReferencesFilter
    Inherits MemoryStream

        Private ReadOnly outputStream As Stream = Nothing
        Private ReadOnly _IsDevEnvironment As Boolean = False

        Public Sub New(ByVal output As Stream, IsDevEnvironment As Boolean)
            Me.outputStream = output
            Me._IsDevEnvironment = IsDevEnvironment
        End Sub

        Public Overrides Sub Write(ByVal buffer As Byte(), ByVal offset As Integer, ByVal count As Integer)
            ' Convert the content in buffer to a string
            Dim contentInBuffer As String = UTF8Encoding.UTF8.GetString(buffer)

            If Me._IsDevEnvironment Then
                contentInBuffer = contentInBuffer.Replace("<script src=""Scripts/Shared/", "<script src=""Scripts/Shared/hiddenDebug/")
                contentInBuffer = contentInBuffer.Replace("/Scripts/Shared/", "/Scripts/Shared/hiddenDebug/")
                contentInBuffer = contentInBuffer.Replace("/App_Themes/Theme1/Shared.css", "/App_Themes/Theme1/hiddenDebug/Shared.css")
            End If

            Me.outputStream.Write(UTF8Encoding.UTF8.GetBytes(contentInBuffer), offset, UTF8Encoding.UTF8.GetByteCount(contentInBuffer))
        End Sub
    End Class
End Namespace

Global.asax

Global.asax

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    ' Simulate internet latency on local browsing
    If Request.IsLocal Then
        System.Threading.Thread.Sleep(50)
    End If

    Dim currentRelativePath As String = Request.AppRelativeCurrentExecutionFilePath

    If request__1.HttpMethod = "GET" Then
        If currentRelativePath.EndsWith(".aspx") Then
            Dim IsDevEnvironment As Boolean = False
            //Use whatever method you want to determine whether your current environment is a development environment:
            #If CONFIG = "Develop" Then
                IsDevEnvironment = True
            #End If

            Response.Filter =
                New Shared.Code.LinkedReferencesFilter(
                    output:=Response.Filter,
                    IsDevEnvironment:=IsDevEnvironment)
        End If
    End If
End Sub

Troubleshooting: Try unloading and reloading the project with linked items. If that doesn't help, add the hiddenDebug directory to your project. I had to do that, but then I was able to remove it later. It's finicky...it would be nice if Microsoft polished this feature, but I'm set for now.

故障排除:尝试卸载和重新加载项目的链接项。如果这没有帮助,请将隐藏bug目录添加到项目中。我必须这么做,但后来我把它删除了。挑剔…如果微软能改进这一功能,那就太好了,但我现在已经准备好了。

In case you didn't know: when you publish your web application, the source (linked) files are automatically copied to the publish target. Once this is set up, you can forget about it. The best part is, you won't lose Intellisense or quick navigation.

如果您不知道:当您发布web应用程序时,源(链接)文件将自动复制到发布目标。设置好之后,您就可以忘记它了。最棒的是,你不会失去智能或快速导航。

After migrating to TypeScript, most JavaScript file reference challenges will be simplified or eliminated (I'm hoping for easy cross-project referencing like what's available for other managed .NET languages, but there may already be some workarounds to enable such functionality).

在迁移到TypeScript之后,大多数JavaScript文件引用的挑战将被简化或消除(我希望可以轻松的跨项目引用,例如其他托管的. net语言可以使用的内容,但是可能已经有一些变通方法来启用这种功能)。

Please let me know whether it works for you, or if you have a better way.

请让我知道它是否对你有用,或者你是否有更好的方法。