What does <None Remove="..." /> mean in csproj? - .net-core

I'm working with a dotnet core csproj and I've added a new file. It doesn't initially get added to the csproj at all because of convention over configuration. But as soon as I change its Build Action from None to Embedded resource, two entries are written to the csproj file:
<None Remove="MyFile.sql" />
and
<EmbeddedResource Include="MyFile.sql" />
What does that first entry mean? It seems superfluous to me.

The sdk-style projects have a few automatic includes.
By default, the sdk has something like <None Include="**/*"> (simplified) that is added (included) before your project's contents. But you don't want your file to be in the "None" set, but in the "EmbeddedResource" set.
MSBuild doesn't have any problem with the files being in more than one item group, but it should only be in one so IDEs don't get confused (and display the file only once an show the correct build action).
So the two statements mean "remove it from the None set (items) and add it to the EmbeddedResource set (items)".

Related

Generated code in csproj not picked up correctly by build

I have an SDK-style csproj file and I would like to generate some code with NSwag before the build starts.
For this I created a custom target
<Target Name="NSwag" BeforeTargets="BeforeBuild">
<Exec WorkingDirectory="$(ProjectDir)" Command="$(NSwagExe_Net70) openapi2csclient ..." />
</Target>
While this target successfully generates me a client class from the provided swagger definition file, the build only runs successfully after the first build.
On the first build it generates the code and the build fails because the code using the generated code cannot find it.
The errors say The type or namespace 'Foo' does not exist in namespace 'Namespace.Of.Generated.Code'
If I start a second build it builds successfully.
What I would like to achieve is that the code is generated before compiling the code and not having to at least run the build two times for it to complete. I tried several different targets in the "BeforeTargets" attribute like "Compile", "Build", "CoreCompile" but some of them either didn't work at all (probably because they didn't exist) or didn't change the behaviour I get with BeforeTargets="BeforeBuild".
Is there any way to fix this?
It sounds like the classes are generated but not picked up by the build.
Try adding the generated files to the MSBuild Compile item so that the build knows to compile them.
This works for me in both VS and the CLI:
<Target Name="NSwag" BeforeTargets="BeforeBuild">
<Exec WorkingDirectory="$(ProjectDir)" Command="$(NSwagExe_Net70) openapi2csclient ..." />
<ItemGroup>
<Compile Include="MyAutoGeneratedRelativeFolder/**/*.cs" />
</ItemGroup>
</Target>
Just replace MyAutoGeneratedRelativeFolder with the output folder of your code generation.

Adding reference to another project from visual studio code

If a library (eg, on github) doesn't distribute itself via a nuget package, I'd have to manually include it as a reference, correct? I see a lot of reference posts for how to add a reference to a project for Visual Studio, but I can't seem to figure out how to do it on Visual Studio Code.
In this case, I've downloaded the library's zip, and moved the expanded folder into my project, and then tried using <namespace>, which did not work.
EDIT:
I noticed that this downloaded zip contained a .nuspec. Is there something I can do with this file extension to import it in my project?
Let's say you have two projects:
1) Project1.Api
2) Project2.Executable
Command line syntax for dotnet add reference:
cd Project2.Executable
dotnet add reference ../Project1.Api/Project1.Api.csproj
If you check the Project2.Executable.csproj file, you will see the following entry:
<ItemGroup>
<ProjectReference Include = "..\Project1.Api\Project1.Api.csproj" />
</ItemGroup>
Add "vscode-solution-explorer" Extension. It will folder structure as visual studio.
Right click on project --> Add Reference --> Select the reference project from the list.
You can open .csproj file of the project you want to add reference to and add project reference like this:
<ItemGroup>
<ProjectReference Include = "<RELATIVE_PATH_TO_REFERENCE_PROJECT>" />
</ItemGroup>
If the ItemGroup for ProjectReference already exist then you can just add to it.
Example:
<ItemGroup>
<ProjectReference Include = "../MyLibrary.csproj" />
</ItemGroup>
In visual studio, in the solution explorer, expand the project that will reference this other library. You will see "References", right click and choose "Add". Then choose browse on the left. Find your dll in your file system. If vs can't find the library you may need to unzip it. I've read where you may need to copy the dll into the bin folders, I recommend trying it without doing that, then copying it in to them if it fails without them.
Btw Googling "visual studio add reference" comes up with A LOT of great results.

Duplicate 'EmbeddedResource' items were included after migrate to .NET Standard?

Using VS 2017 15.4.0
Following James Montemagno "Upgrading to Xamarin.Forms to .NET Standard"
https://channel9.msdn.com/Shows/XamarinShow/Snack-Pack-15-Upgrading-to-XamarinForms-to-NET-Standard?ocid=player
When trying to Clean/Build I am receiving the error:
Severity Code Description Project File Line Suppression State
Error Duplicate 'EmbeddedResource' items were included. The .NET SDK includes 'EmbeddedResource' items from your project directory by default. You can either remove these items from your project file, or set the 'EnableDefaultEmbeddedResourceItems' property to 'false' if you want to explicitly include them in your project file. For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: 'App.xaml'; 'MainPage.xaml' App5.core C:\Program Files\dotnet\sdk\2.0.2\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.DefaultItems.targets 274
Any solution please?
Found the solution...
Right click on the new .NET Standard project I have created "App5" and choose Edit App5.csproj
I have deleted this code from the file and the error gone.
<ItemGroup>
<EmbeddedResource Include="App.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="MainPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
I found various suggestions, but this answer was easily the best for me, both in simplicity and elegance:
In Solution Explorer, enable "Show All Files". This displays all files in each folder, including those excluded from the project.
For each item listed in the error message:
Exclude from project
Include in project
Then
In Solution Explorer, disable "Show All Files".
My mistake was that I added embedded resource while simulator with app was running.
Soo... I had THIS added automatically inside .csproj file:
<EmbeddedResource Include="**/*" />
Remove it, and then everything should be fine
According to bugzilla of xamarin at some point you were required to insert to make it work with the new csproj format.
<ItemGroup>
<!-- https://bugzilla.xamarin.com/show_bug.cgi?id=55591 -->
<None Remove="**\*.xaml" />
<Compile Update="**\*.xaml.cs" DependentUpon="%(Filename)" />
<EmbeddedResource Include="**\*.xaml" SubType="Designer" Generator="MSBuild:UpdateDesignTimeXaml" />
</ItemGroup>
Source
I would imagine that xamarin decided to add that to the default build targets now.
So to fix it you have to do the following:
Open your shared .csproj file.
Remove all Itemgroups related to adding xaml pages and *.cs
clean + rebuild.
It happened to me in MS Visual Studio for Mac after I have added two font files as embedded resources.
These files were titled with the same prefix (Lora-Regular.ttf & Lora-Bold.ttf) and it looks like my IDE did handle this in a bad way.
Indeed, the following weird line was inserted in my .csproj file :
<EmbeddedResource Include="**/*" />
All I did was removing this line and error disapeared.
Try to clean it manually with these steps:
Close your VS
remove bin and obj folders from iOS, Android and the Common (Your project name) folder.
remove all content from the packages folder
open a terminal, navigate to your projects folder and type nuget locals all -clear
then type nuget restore
and finally open VS again and let me know if the problem still exists
For me issue was in one file name. I used underscore (_) in the filename. I was working with file name AppResource.zh_cn.resx. May be it could help someone.
for me unloading and reloading project again worked!

Specifying folders not to sync in Web Deploy

I use the following script to deploy my ASP.NET MVC app to our web server:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MySolution.sln^
/p:Configuration=TeamCity-Test^
/p:OutputPath=bin^
/p:DeployOnBuild=True^
/p:DeployTarget=MSDeployPublish^
/p:MsDeployServiceUrl=https://mywebserver.com:8172/msdeploy.axd^
/p:username=MyDomain\MyUser^
/p:password=MyPassword^
/p:AllowUntrustedCertificate=True^
/p:DeployIisAppPath=mywebsitename.com^
/p:MSDeployPublishMethod=WMSVC
Now I need to specify to not sync the /uploads folder. Can I specify that in this script? Thanks!
Clarification:
I have the Uploads folder in my project. I'd like for Web Deploy to create the folder. I do not want it to delete the folder/subfolders/files from my web server because it contains user-uploaded content.
Clarification #2:
I just found the SkipExtraFilesOnServer=True option. However, I don't want this to be global. I'd like to set it to a single folder.
UPDATE:
Apparently, what you really want is prevent web deploy from removing existing directory on the destination server, but still have the folder created in case it's not there. You can accomplish this as follows:
create YourWebProjectName.wpp.targets file next to you the project file with the following content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MsDeploySkipRules Include="SkipELMAHFolderFiles">
<SkipAction></SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>$(_DestinationContentPath)\\NameOfYourFolder\\.*</AbsolutePath>
<Apply>Destination</Apply>
<XPath></XPath>
</MsDeploySkipRules>
<MsDeploySkipRules Include="SkipELMAHFolderChildFolders">
<SkipAction></SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>$(_DestinationContentPath)\\NameOfYourFolder\\.*\\*</AbsolutePath>
<Apply>Destination</Apply>
<XPath></XPath>
</MsDeploySkipRules>
</ItemGroup>
</Project>
Change NameOfYourFolder and YourWebProjectName accordingly. This assumes, you have it in the root, I believe, you can use relative path if it's not the case.
The first MsDeploySkipRules entry tells webdeploy not to remove any files in Name_OfYourFolder.
The second MsDeploySkipRules tells webdeploy not to remove any child folders in Name_OfYourFolder.
Also, to have the folder created if it's not present on the destination server, you have to do the following:
include the folder into the project
add a dummy DeployemntPlaceholder.txt file into it and include it into the project as well
DeployemntPlaceholder.txt is required to tell MSBUild to add the folder into the package: empty folders are ignored.
I've tested this approach and it works fine when you run publish in the manner you've shown. I've used this answer to get the msbuild items syntaxt right. I believe, this is a MSBuild way to customize flags, passed to webdeploy by MSBuild Deployment Pipeline.
If you ran MSDeploy directly, you could use skip arguments in the following manner:
-skip:objectname='filePath',absolutepath='logs\\.*\\someNameToExclude\.txt'
UPDATE 2
You might also want to have ACL write permissions set on your \Uploads folder - there's a complete guide to do this: Setting Folder Permissions On Web Publish
Conserning the original question "Specifying folders not to sync in Web Deploy", the easiest way to do this is as follows:
You can create a publish profile and add the following lines:
<PropertyGroup>
<ExcludeFilesFromDeployment>
File1.aspx;File2.aspx
</ExcludeFilesFromDeployment>
<ExcludeFoldersFromDeployment>
Folder1;Folder2
</ExcludeFoldersFromDeployment>
</PropertyGroup>
I've tested this approach for excluding files using publish profiles. An easy guide is here (scroll to Edit the .pubxml file to exclude robots.txt section).
You can also do this in .wpp.targets file or edit you csproj. See more information at Web Deployment FAQ for Visual Studio and ASP.NET

Make MSDeploy (Visual Studio) not delete App_Data folder but delete everything else

I'm using Visual Studio's Publish button to deploy my website, and want a different App_Data folder on the server. There's a checkbox for Leave extra files on destination (do not delete) which prevents my App_Data folder from getting deleted, but then it'll eventually accumulate a lot of vestigial files as the website changes.
Is there any way to make it exclude just App_Data when it deletes everything?
It can be done when you invoke msdeploy manually - just add the following parameter:
-skip:Directory=\\App_Data
See Web Deploy Operation Settings. The path is a regular expression, so it is quite flexible.
If you deploy using the VS-generated ProjectName.deploy.cmd script, you can also pass this parameter in the _MsDeployAdditionalFlags environment variable (when running that script).
This is the best I've come up with for our needs (we have a similar situation as you). I haven't tried integrating it with VS's Publish button, since we deploy from command line.
EDIT:
I have learned a few things about MSDeploy since I posted this answer, so I thought I'd update it now.
First of all, the above skip rule skips any operations on the matching path (App_Data). If more granular control is needed, a more verbose syntax is available. For example, to skip only deletes (to keep any extra files on target server, but add any new ones and update existing ones):
-skip:skipaction='Delete',objectname='filePath',absolutepath='\\App_Data\\.*' -skip:skipaction='Delete',objectname='dirPath',absolutepath='\\App_Data\\.*'
This skips deletes of all files and all subfolders (with all their content) in App_Data, but doesn't prevent adds and updates.
Another useful thing is that skip rules can be defined in the project file (.csproj) so that they are automatically included in the .deploy.cmd script generated along with the package. This makes it unnecessary to pass them to the script through _MsDeployAdditionalFlags.
The above skip rule will be added if the following is included in csproj file:
<PropertyGroup>
<OnBeforePackageUsingManifest>AddCustomSkipRules</OnBeforePackageUsingManifest>
</PropertyGroup>
<Target Name="AddCustomSkipRules">
<ItemGroup>
<MsDeploySkipRules Include="SkipDeleteAppData">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>$(_Escaped_PackageTempDir)\\App_Data\\.*</AbsolutePath>
<XPath>
</XPath>
</MsDeploySkipRules>
<MsDeploySkipRules Include="SkipDeleteAppData">
<SkipAction>Delete</SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>$(_Escaped_PackageTempDir)\\App_Data\\.*</AbsolutePath>
<XPath>
</XPath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
(the names AddCustomSkipRules and SkipDeleteAppData are completely arbitrary; $(_Escaped_PackageTempDir) is supposed to be possibly needed, but in practice I've always seen it evaluate to an empty string)
See Web Deploy: Customizing a deployment package and How to set MSDeploy settings in .csproj file for more info.
One caveat: this only adds those rules to the .deploy.cmd script, so it is useless if you want to use the graphical IIS Manager for package deployment, as it doesn't use that script (the same probably goes for deployment from VS, but I haven't checked).
From my experience, MsDeploySkipRules are only run when deploying from the command line.
If you are publishing from Visual Studio to Azure (or using another Web Deploy method), you can set the following when Publishing.
Remove additional files at destination
Exclude files from the App_Data folder
When "Remove additional files at destination" is checked, it will make a comparison between the files and folders you are deploying and the ones on the server.
Be warned, you may run into issues if you have User Generated content, e.g. Uploads. But this could be worked around by storing those folders in a different location, e.g. S3 / Azure Storage.
From Powershell, if you want to use msdeploy.exe or the myproj.deploy.cmd (Deploying Web Packages) produced when publishing with Web Deploy Package, in order to to skip deleting the App_Data folder and avoid the
All arguments must begin with "-"
error, you have to enclose the skip directive in triple quotes, e.g. :
myproj.deploy.cmd /y /u:myusername /p:mypass """-skip:Directory=\\App_Data"""
Have you looked at Package/Publish Web in the project settings, because you can tell it to exlude files in the App_Data folder.
For asp.net core web apps use MsDeploySkipRules in csproj.
<ItemGroup>
<MsDeploySkipRules Include="CustomSkipFile">
<ObjectName>filePath</ObjectName>
<AbsolutePath><dir_name>\\app_data</AbsolutePath>
</MsDeploySkipRules>
<MsDeploySkipRules Include="CustomSkipFile">
<ObjectName>dirPath</ObjectName>
<AbsolutePath><dir_name>\\app_data</AbsolutePath>
</MsDeploySkipRules>
</ItemGroup>
Replace <dir_name> with your root folder
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/visual-studio-publish-profiles?view=aspnetcore-2.1#exclude-files
This isn't ideal since you may be copying a lot of files doing this (I'm not), but here's my solution for backing up a folder. Adapted to move the folder to the location from which it will be published, during the publish process. Put this in your pubxml file:
<Project>
...
<Target Name="PreserveSelectedFolder" AfterTargets="GatherAllFilesToPublish">
<ItemGroup>
<SITEDIR Include="$(publishUrl)\App_Data\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(SITEDIR)"
DestinationFolder="$(ProjectDir)\obj\$(Configuration)\Package\PackageTmp\%(RecursiveDir)"></Copy>
</Target>
</Project>
And if you just want to do any number of specific known files, do one Copy block per file:
<Target Name="PreserveSelectedFiles" AfterTargets="GatherAllFilesToPublish" >
<Copy SourceFiles="$(publishUrl)\MYFILENAME.EXT"
DestinationFolder="$(ProjectDir)\obj\$(Configuration)\Package\PackageTmp\"
Condition="Exists('$(publishUrl)\MYFILENAME.EXT')"></Copy>
</Target>
Put this in your pubxml file:
<ExcludeApp_Data>True</ExcludeApp_Data>

Resources