I'm trying to split out my web resources, images/JS/CSS into another project within my Visual Studio solution so that I can share this across all projects.
I've tried setting this up as per link below
How do you share scripts among multiple projects in one solution?
However I keep on getting
Web resource '/Scripts/myscript.js' was not found.
I'm using "add as link" to link to resources from different project but they don't see to get copied over on build.
Thanks
This is a better way of doing it.
Using information from
Copy file(s) from one project to another using post build event...VS2010
and
http://greenicicleblog.com/2010/12/01/link-whole-directories-into-visual-studio-projects/#comments
I created a folder called WebAssets along side my project. I copied all my scripts, css and images to this folder.
I then added
<Content Include="..\WebAssets\**\*.*">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
</Content>
to my csproj file
This worked when I published the site, but not after a build. The local webserver kept on complain about missing files.
So I added a post build event to project, like so.
<PropertyGroup>
<PostBuildEvent>xcopy /S /Y "$(SolutionDir)WebAssets" "$(ProjectDir)" </PostBuildEvent>
</PropertyGroup>
This copied all the files from the WebAssets folder to the correct location.
This example shoes the best way I have come up with so far
http://www.codeproject.com/Articles/12997/WebResource-ASP-NET-2-0-explained
However I'm not that keen on it because it means that I have to create many manual entries in the AssemblyInfo.cs file and then modify css and js to point images. Like so
<img src='<%=WebResource("MyWebResourceProj.MyResources.Test.gif")%>'>
Related
I need to create a .NET Standard 2.1 NuGet package that contains a JavaScript file which will be added to my consuming application in the following path:
/wwwroot/js/myFileFromNugetPackage.js
(the consuming application happens to be a Blazor Server app)
I followed one example which used a *.targets file, but it didn't work for me.
The closest I got was to set up my NuGet project as follows:
Create a top level folder named "wwwroot"
Add the file "wwwroot/js/myFileFromNugetPackage.js"
In the properties for that JS file, set "Build Action = Content" and "Copy to Output Directory" = "Copy Always"
I publish this to my private NuGet library.
I then add that package to my Blazor (.Net Core 3.1) application.
When I look in Visual Studio's Solution Explorer, what I see looks promising:
/wwwroot/js/myFileFromNugetPackage.js
However...
If I manually create a new file in the same directory, so I now have:
/wwwroot/js/manuallyAddedFile.js
/wwwroot/js/myFileFromNugetPackage.js
When I go to the properties of the two files, I see different paths:
C:{some path}\MyApplication\wwwroot\js\manuallyAddedFile.js
and
C:\Users\{me}\.nuget\packages\{myNuGetPackage}\{version}\contentFiles\any\netstandard2.1\wwwroot\js\myFileFromNugetPackage.js
And unsurprisingly, when I attempt to use either of those JS file using Blazor's JS Interop, I can use the one I manually entered, but it can't find the one from my NuGet package. The F12 developer tools show only the manually created one present on the Client.
So, my question is: How do I set up my NuGet project to write a JS file so that it ends up in the correct directory?
And unsurprisingly, when I attempt to use either of those JS file
using Blazor's JS Interop, I can use the one I manually entered, but
it can't find the one from my NuGet package.
Because you can only in Blazor application (new SDK format) using packagesreference nuget management format, so you import package can only by reference links will be in the form of your files into the project in a package, so myFileFromNugetPackage. Js properties displayed in the path ../. Nuget/packages .
This is also a feature of the pacakgesreference nuget management format. By the way, this is not such case with packagesconfig nuget management format.
When you add a new item which means that you have created a file under your current solution, so you can find the new file under the solution.
I followed one example which used a *.targets file, but it didn't work
for me. So, my question is: How do I set up my NuGet project to write
a JS file so that it ends up in the correct directory?
Solution
To solve your problem you can add a target file to the nuget package which copys the actual file to the project so that it will be referenced in the main project and not referenced in the link.
I tried your link demo and it can successfully achieve your goal.
The core is this paragraph
<ItemGroup>
<SourceScriptFiles Include="$(MSBuildThisFileDirectory)..\content\scriptsToGenerate\*.js" />
</ItemGroup>
<Target Name="CopyScriptsToProject" BeforeTargets="Build">
<Copy SourceFiles="#(SourceScriptFiles)" DestinationFolder="$(ProjectDir)\wwwroot\js\scriptsToGenerate\"
/>
</Target>
Note:
In some cases, you might want to add custom build targets or properties in projects that consume your package, such as running a custom tool or process during build. You do this by placing files in the form <package_id>.targets or <package_id>.props (such as Contoso.Utility.UsefulStuff.targets) within the \build folder of the project.
This pre-processing target can only be executed at build time,
So I suspect you can't find the JS file in the main project without building the project. Hope it could help you.
I created a simple standalone SQL-table-to-class generator as a WPF application.
When I save files (e.g. a .cs class file) from that application into the directory structure of a separate web application I'm working on, it is of course not added to the solution. I have to manually add it in.
Is there a way I can automatically tag it/flag it or whatever, to be included in the web application solution?
The only solution I know of is to manually modify the .proj file and add a content include directive for the directories you want with a wildcard.
<Content Include="SomeDirectory\*" />
You will need to do this for each directory and it isn't recursive. The major down-side though, is that you must reload the project for it to pick up new files.
Personally, I consider this to be a bit of hack and would never use it in a serious project.
I am using Webpack for my front-end, which will generate files with hashes in the filenames. Because of this, Visual Studio does not see them as included, and my publish fails.
My current flow is Publish -> Fail -> Add missing files, remove deleted ones -> Publish again.
Is it possible to just tell Visual Studio to include all files in a folder, no questions asked?
I already tried modifying the csproj like so:
<Content Include="SiteContent\**" />
But that does not work when publishing; I run the webpack tool in my pre-build script.
This worked (with modifications) for me: https://stackoverflow.com/a/9438419/1971537
The key was changing to
My situation is that after a successful build, powershell scripts move around and rename FE resources (js, css, html, vendor stuff) and given the renaming (for caching issue prevention), the filenames are never exactly the same, and the folder I think even gets axed. Changing this to afterbuild caused the files to get correctly added to the project after the build and the azure web deploy correctly picked them up.
Another hacky option I found that I played with initially just to see if my deployment was successful at all: https://msdn.microsoft.com/en-us/library/ee942158(v=vs.110).aspx#can_i_exclude_specific_files_or_folders_from_deployment
I tried the other two options for the Package/Publish Web tab (All files in this project and All files in the project folder) and this worked but with the issue of having to remove a ton of junk files just to get a couple files I wanted.
Hope this helps, I didn't figure anything out on my own but I eventually scraped it together. Go upvote the guy I linked first for his reply.
I have read this post thoroughly: How does Visual Studio's source control integration work with Perforce? and found it very informative. However, I have a specific issue that is blocking my use of Perforce in VS.
For the most part, I have no complaints about the plug-in (I'm still using the P4VSCC plug-in because the new plug-in requires conversion by the entire team which can't happen at this time). Once I understood the idiosyncracies, I've had only one problem working with the plug-in.
Our solutions contains many projects that are built into a single deployment package. As such, each assembly is versioned the same. To accomodate this, and other common aspects, we have defined a common "SharedVersionInfo.cs" file which contains the AssemblyVersion and AssemblyFileVersion attributes typically found in the AssemblyInfo.cs file. This file is stored in an Assets folder beneath the solution folder and added to each project's Properties folder as a linked file. This works great from a version management perspective as we only have to change the version in one place and all assemblies are updated. However, Perforce has a problem with this when a new developer first opens the solution or when a new project is added. The only remedy we have currently is to remove all of the linked files (there are 3 per project in this solution), bind the project to source control, then re-add the linked files.
This isn't such a big deal when we add a new project but the solution contains 80 projects (and counting), so this isn't a viable remedy for a new developer!
My understanding is that the problem has to do with where VS thinks the binding root for each project is. After some research, I was led to find where the MSSCCPRJ.SCC files are for the projects. I found there are numerous SCC files scattered throughout the solution structure. So...
First question: Why are there multiple MSSCCPRJ.SCC files in my solution structure?
We also have several shared/common projects that we use in our solutions. This leads to the following folder structure:
/Source
/CommonTools
/ProjectA
ProjectA.csproj
/ProjectB
ProjectB.csproj
/MySolution
/Assets
SharedVersionInfo.cs
/Project1
Project1.csproj
/Project2
Project2.csproj
:
/ProjectZ
ProjectZ.csproj
MySolution.sln
Where both ProjectA and ProjectB are part of MySolution.sln
Second Question: How can I setup the bindings so the /Source folder is considered the root? This would ensure that all projects included in the solution are under the same binding root. Perforce considers this folder to be the root, how do I get VS and the plug-in to do the same?
Since no one else has offered up a solution, I thought I'd follow-up with my own findings for anyone else that comes across the thread.
First, I still have no idea why Visual Studio creates multiple MSSCCPRJ.SCC files but these are the key to establishing the "binding root" for a solution. It is critical that this file exist at the highest level necessary so that ALL of the projects in the solution are in sub-folders relative to the location of this file. In my example above, the MSSCCPRJ.SCC needed to be located in the /Source folder. Having it in the /MySolution folder caused the original problem when adding projects from /CommonTools into the solution.
That said, resolving the issue was no easy task. I had to manually edit the .sln and all of the .csproj files in Notepad. What I found was that some of the .csproj files had the following elements identifying the source control settings:
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
I don't know what SAK stands for, but my understanding is this tells Visual Studio to use the binding information contained in the .sln file.
I had to change these to:
<SccProjectName>Perforce Project</SccProjectName>
<SccLocalPath>..\..</SccLocalPath>
<SccAuxPath />
<SccProvider>MSSCCI:Perforce SCM</SccProvider>
where the SccLocalPath value is the relative path from the .csproj file to the MSSCCPRJ.SCC file.
I also had to change the SccLocalPathX and SccProjectFilePathRelativizedFromConnectionX statements for each project in the .sln file. The SccLocalPathX value should be the relative path from the .sln file to the MSSCCPRJ.SCC file - a dot (.) if in the same folder. SccProjectFilePathRelativizedFromConnectionX should be the relative path from the binding root to the .csproj file.
I wish I could say that having that in place, I never had to repeat these steps. Unfortunately, I still have to go in and make corrections every time I added a new project to the solution. Visual Studio still wants to use SAK for the elements in the .csproj file and sometimes the values in the .sln file aren't quite right.
But, at least I know what to look for and what needs to be done to achieve my goals. If anyone else has a better solution or a way to configure VS and/or Perforce so these settings are created correctly up-front, I'll gladly give credit.
Hope that helps...
I have some content files that I would like to share between a number of projects in Visual Studio.
I have put these files in their own project, set the build action to "Content", and the copy to output directory to "Copy if newer". I would like all these files to be copied to the bin/debug directory of the projects that reference them.
I can get it to work by including a reference to the "contents" project in each of the projects that need the files, but that requires that a minimal assembly be generated (3K). I assume there is a way, using MSBuild, to make this all work without creating the empty assembly?
Thanks to everone who took the time to make a suggestion about how to solve this problem.
It turns out that if I want my compiled content files to be treated like content files (in that they get copied to the output directory of any other project that references my project), I need to create a target which runs before GetCopyToOutputDirectoryItems, and add the full path of the compiled content files to the AllItemsFullPathWithTargetPath ItemGroup. MSBuild calls GetCopyToOutputDirectoryItems for projects on which the current project depends, and uses the resulting file list to determine the files that are copied along with the assembly.dll. Here is the XML from my .csproj, just in case someone else has a similar problem.
I have a custom task called "ZipDictionary", and I accumulate all the files that I am going to compile in an ItemGroup called DictionaryCompile. My target, "FixGetCopyToOutputDirectoryItems" is executed before "GetCopyToOutputDirectoryItems". I don't do the actual compilation there, since this target can be called multiple times by referencing projects, and it would hurt performance. The target does some transforms to get the post-compilation file names, and then returns the full paths to all the files, since relative paths will not work when copy is called from the referencing project.
<ItemGroup>
<DictionaryCompile Include="Dictionaries\it-IT.dic">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</DictionaryCompile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="ZipDictionary" AssemblyFile="..\LogicTree.DictionaryCompiler\bin\Debug\LogicTree.DictionaryCompiler.dll"/>
<Target Name="BeforeCompile">
<Message Text="Files #(DictionaryCompile)" Importance="high" />
<ZipDictionary DictionaryFiles="#(DictionaryCompile)" OutputDirectory="$(OutputPath)">
<Output TaskParameter="OutputFiles" ItemName="DictionaryOutputFiles" />
</ZipDictionary>
</Target>
<Target Name="FixGetCopyToOutputDirectoryItems" BeforeTargets="GetCopyToOutputDirectoryItems">
<ItemGroup>
<_DictionaryCompile Include="#(DictionaryCompile->'$(OutputPath)Dictionaries\%(FileName).ltdic')" />
</ItemGroup>
<AssignTargetPath Files="#(_DictionaryCompile)" RootFolder="$(MSBuildProjectDirectory)\$(OutputPath)">
<Output TaskParameter="AssignedFiles" ItemName="_DictionaryCompileWithTargetPath" />
</AssignTargetPath>
<ItemGroup>
<AllItemsFullPathWithTargetPath Include="#(_DictionaryCompileWithTargetPath->'%(FullPath)')" Condition="'%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
<_SourceItemsToCopyToOutputDirectoryAlways Include="#(_DictionaryCompileWithTargetPath->'%(FullPath)')" Condition="'%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='Always'" />
<_SourceItemsToCopyToOutputDirectory Include="#(_DictionaryCompileWithTargetPath->'%(FullPath)')" Condition="'%(_DictionaryCompileWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
</ItemGroup>
</Target>
A better possible solution would be to
place a common directory in the solution dir and place your common content files there.
in VS, in each project that should share this content, right-click add existing item, browse to the desired item(s), select, click the down-arrow on the add button and select add as link. In the project, you will notice the files are added with a 'shortcut' overlay.
In the project, select the newly added links and right-click->properties and select Build Action: content, Copy To Output Directory: Copy Always.
This is a simple solution to the problem given.
I use this technique for things like SQL scripts and partial config files (using configSource) with great success. This allows me to make changes to these files in a single location with the assurance that they will be propigated throughout the solution.
A more robust solution would be to create a project with embedded resources. This requires a bit more work to manage the content on the receiving end but may be worth it in the long run as having a bunch of loose artifacts flying about can become problematic.
Hope that helps.
A similar solution like the one Sky suggested can be found in my answer to "Is there a way to automatically include content files into asp.net project file?".
It allows to share your content but you must not touch the folder or its content inside VS because this breaks the recursive path.
This approach works best for auto-generated content - you don't have to bother about including new content files to your solution.
And of course you can reuse this in multiple solutions/projects.
We do something similar where we have "...ReleaseBuilds" that reference dlls and content we require for specific projects. Compiling copies everything to the bin debug folder and indeed creates the empty assembly.
Within Visual Studio we have a post-build event in the "...RealeaseBuild" (in project properties) that copies/deletes or run batch files to make sure we have all the files (configs, services etc etc) required and to delete the empty assembly.
HTH