adding extra files to published MVC API project - c#

I am trying to add an extra XML file to a publishing process. I have a MVC API project which also has another project (V1.0) for controllers. We are using the self documenting help functionality which creates the .XML files for each project. When building on the local machine it all works but when publishing (with wizard) it will not include this file.
I have been trying to update the publish profile (.pubxml) file as described here:
http://www.asp.net/mvc/tutorials/deployment/visual-studio-web-deployment/deploying-extra-files
but without success. I can see the following is happening:
I do a clean to ensure nothing hanging around.
I publish with wizard
I can see in apiproject\bin\ there are all the files including the apiprojectv1 xml and dll files
I can see in apiproject\obj\x86\Release\AspnetCompileMerge\Source\bin it has the apiprojectv1 dll but not the xml file
I can see the same as above in apiprojet\obj\x86\Release\AspnetCompileMerge\TempBuildDir\bin
I can see the same as above in apiproject\obj\x86\Release\Package\PackageTmp\bin
I am not sure why the file is not being copied across. This is my full pubxml file:
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<publishUrl>\\myserver\wwwroot\apiproject</publishUrl>
<DeleteExistingFiles>False</DeleteExistingFiles>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\bin\apiprojectv1.XML" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension) </DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
</Project>
EDIT
I had forgot one major part, to put the below at the bottom of the pubxml file:
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
I do not get the file, but now get an error regarding the file not being found, (which I can now debug).

I had missed two things:
The second property group to actually tell it to perform the action.
The path was not right, had to use project directory path
Now looks like this and works:
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<publishUrl>\\myserver\wwwroot\apiproject</publishUrl>
<DeleteExistingFiles>False</DeleteExistingFiles>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="$(MSBuildProjectDirectory)\bin\apiprojectv1.XML" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension) </DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
</Project>

Related

Producing Executable for a C# project in linux

I want to know how to produce a c# executable file on Linux as when I build all I get is a DLL file in the bin folder that I don't know how to execute.
Note: I'm using vscode as my code editor and Manjaro is my Linux distro.
Did you try command?
dotnet app_name.dll
I guess a Publish Profile is What You are looking for.
Add a file named MyPublishProfile.pubxml to your project with this content:
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<DeleteExistingFiles>false</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net6.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<ProjectGuid>c21872b8-42b3-418a-ab47-103a60e7cd6c</ProjectGuid>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>
save it and edit it (follow the provided links). then you can run
dotnet publish -p:publishProfile=MyPublishProfile
then you should have your excecutable. maybe you have to chmode it. you can read more here

Multiple binaries from a single DotNet Core project configuration file

I have code for a bunch of CLI utilities made to test/showcase a network library. The library is compiled into an assembly - DotNet Core DLL.
I have several CLI examples showing how to use the library, for example, one search is using paging functionality and another returns everything etc. Basically, each is a short standalone CLI program.
I have CS source files and csproj file targeting dotnet core. Below is the configuration:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="mylib>
<HintPath>../../bin/Debug/netstandard2.0/publish/mylib.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
I want to have one executable for each source file e.g. PGSample.cs will get compiled into PGSample.exe etc. How would I about achieving this?
I'm afraid you can have only one output per csproj, but there are some tricks to manage multiple projects easier.
You can put common build settings into a file named Directory.build.props in the root project folder, e.g.:
<Project>
<PropertyGroup>
<Authors>Your name here</Authors>
<Company>Your company</Company>
<Product>The project name</Product>
<Version>1.6.18</Version>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<!-- e.g. bin/Release_net48/foo_cli/ -->
<OutputPath>$(SolutionDir)bin\$(Configuration)_$(TargetFramework)\$(MSBuildProjectName)</OutputPath>
<TargetFrameworks>net48</TargetFrameworks>
</PropertyGroup>
</Project>
Then, add one subdirectory and minimal csproj file per output, e.g.
libfoo/libfoo.csproj: <Project Sdk="Microsoft.NET.Sdk" /> (really, that's it!)
foo_cli/foo_cli.csproj:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><OutputType>Exe</OutputType></PropertyGroup>
<ItemGroup><ProjectReference Include="..\libfoo\libfoo.csproj" /></ItemGroup>
</Project>
Iff you have only one library and a lot of executables, you might even add your executable settings to the Directory.build.props:
[..]
<PropertyGroup Condition=" $(MSBuildProjectName) != 'libfoo'">
<OutputType>exe</OutputType>
</PropertyGroup>
<ItemGroup Condition=" $(MSBuildProjectName) != 'libfoo'">
<ProjectReference Include="..\libfoo\libfoo.csproj" />
</ItemGroup>

How to execute msbuild /t:updateuid for all projects in a solution?

is there an easy way to execute msbuild /t:updateuid <project file> for all projects in a solution?
I have a huge solution with more than 150 projects and want to set Uids to all *.xaml files in all projects in the solution. I don't want to add this line to every project, but execute it from one place. Thus I can easilly control the execution of the command.
For example during the development phase I would like to disable the command to make the build process faster and just before the test phase i would like to enable it from one place. Any suggestions are wellcomed.
Regards
I managed to solve my problem using the information on the this blog.
The idea is to inject a custom .targets file, which will be processed by msbuild for every project. Imagine we have the following solution structure:
SolutionFolder
MySolution.sln
after.MySolution.sln.targets
UpdateAutomationIds.targets
The after.MySolution.sln.targets file will be processed by the msbuild. It will inject our UpdateAutomationIds.targets file to be executed for every project in the solution. Just replace MySolution with the name of your solution.
after.MySolution.sln.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CustomAfterMicrosoftCommonTargets>$(MSBuildThisFileFullPath)</CustomAfterMicrosoftCommonTargets>
<SolutionPath>$(SolutionPath);CustomAfterMicrosoftCommonTargets=$(MSBuildThisFileDirectory)UpdateAutomationIds.targets</SolutionPath>
</PropertyGroup>
</Project>
UpdateAutomationIds.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="UpdateAutomationIds" Condition="'$(MSBuildProjectExtension)'=='.csproj'" BeforeTargets="Build">
<Message Text="Updates automation ids. Project: $(MSBuildProjectFullPath)" Importance="high"/>
<Exec Command=""$(MSBuildToolsPath)\msbuild.exe" /t:updateuid "$(MSBuildProjectFullPath)""/>
<Exec Command=""$(MSBuildToolsPath)\msbuild.exe" /t:checkuid "$(MSBuildProjectFullPath)""/>
</Target>
</Project>

Custom settings in MSBuild for Windows Phone

I have a Jenkins server that executes MSBuild for me.
There's a whole bunch of builds that need to be done, they all use the same solution file but for every build some custom settings need to change.
The app needs to be able to read these settings.
For example if I'd build like this:
msbuild MyProject.sln /p:MyVar=SomeValue
Then when the app launches, it should be able to retrieve what the value is of MyVar.
For example, the app should be able to show a messagebox when it starts with the title 'SomeValue'.
I know I can define properties as described here by Microsoft, but I can't figure out how to read those properties when the app starts.
Or maybe I'm just looking at a completely wrong way of doing it.
Any ideas?
You would need msbuild to create a text file with the value inside of it. For that you can use the TemplateFile task of the MSBuild.Community.Tasks.Target in your msbuild file.
CreateAppVarFile.targets file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksPath>$(SolutionDir)\.build</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" />
<Target Name="CreateAppVarFile">
<ItemGroup>
<TemplateContext Include="MyVar">
<ReplacementValue>$(MyVar)</ReplacementValue>
</TemplateContext>
</ItemGroup>
<TemplateFile Template="$(MSBuildThisFileDirectory)appvar.txt" OutputFilename="$(ProjectDir)appvar.txt" Tokens="#(TemplateContext)"/>
</Target>
</Project>
This target would then be included in your project file
<Import Project=".\build\CreateAppVarFile.targets" />
<Target Name="BeforeBuild" DependsOnTargets="CreateAppVarFile">
and your .\build\appvar.txt template file in the folder where your CreateAppVarFile.targets file is located can look just like this:
$(MyVar)
and be read from your app during runtime. Don't forget to include the appvar.txt in your project. It will contain:
SomeValue

Msbuild for copying assemblies to a few folders of applications?

I have a VS solution that contains a few applications and public APIs to be published along with shared libraries. I have some shallow experience in crafting msbuild file like this one.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TPath>C:\Program Files (x86)\MSBuild\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks</TPath>
<ETPath>C:\Program Files (x86)\MSBuild\ExtensionPack\4.0\</ETPath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup>
<SolutionFile Include="MyApplications.sln" />
</ItemGroup>
<Target Name="Build" Outputs="#(CollectedBuildOutput)">
<MSBuild Projects="#(SolutionFile)" Targets="Rebuild" BuildInParallel="True"
Properties="BuildingSolutionFile=true; Configuration=$(Configuration); Platform=$(Platform); TargetFrameworkVersion=$(TargetFrameworkVersion); WarningLevel=3"
SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)">
<Output TaskParameter="TargetOutputs" ItemName="CollectedBuildOutput"/>
</MSBuild>
</Target>
</Project>
Then I run
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MyProjects.msbuild /p:outdir=C:\VSProjectsRelease\MyApplications\Release\
So all assemblies will go to the same directory. So far so good. However, if I want to zip files for each application, or harvest files for Wix setup projects, troubles will emerge.
For example, in MyApplications.sln, I have 10 projects, 3 of which are applications say AppA, AppB and AppC.
I would like to run a single msbuild file which will create 3 folders of applications, and have assemblies copied to there without explicitly defining dependencies since Sln and csproj files already have the knowledge. And I would want msbuild will build each project only once. How to do this?

Categories