Visual Studio “Add As Link” not working while debugging

前端 未结 4 1033
灰色年华
灰色年华 2020-12-24 02:28

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 b

相关标签:
4条回答
  • 2020-12-24 02:36

    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.

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

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

    Single CSS File

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

    JavaScript directory

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

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

    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

    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.

    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.

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

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

    0 讨论(0)
  • 2020-12-24 02:37

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

    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.

    0 讨论(0)
  • 2020-12-24 02:44

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

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

    0 讨论(0)
  • 2020-12-24 02:47

    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.

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

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

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

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

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

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

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

    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.

    0 讨论(0)
提交回复
热议问题