Prevent application parts from beign copied to the output directory - c#

I've split my ASP.NET Core application into multiple projects using the Application Parts feature. One of them is where I manage my communication UI. Within that project, I've got the extension method below, which I use to include the shared communication content in my main project,
public static IMvcBuilder AddCommunicationUI(this IMvcBuilder builder)
{
builder.AddApplicationPart(typeof(ServiceCollectionExtensions).Assembly);
builder.Services.Configure<MvcRazorRuntimeCompilationOptions>(options =>
{
options.FileProviders.Add(new EmbeddedFileProvider(typeof(ServiceCollectionExtensions).Assembly));
});
return builder;
}
My problem is that when published, all cshtml files content from the communication project are being copied to output directory.
Is there any way of preventing that kind of behavior?

I have a suggestion as below:
If you don't want to publish some files, you need to set in csproj file.Sample to prevent files from being published like :
<ItemGroup>
<Content Update="wwwroot\data\file.json">
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content>
</ItemGroup>

Related

How to share static files across solution in Visual Studio 2022?

I'm developing a solution containg multiple web projects that share static content like javascript files.
I've done some research and it seems that proper way of handling it is to add shared files as solution items and then add them as links to web projects:
Then web projects should implement copying these files to output directory (I set them to Content beforehand):
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
<Copy SourceFiles="%(Content.Identity)"
DestinationFiles="%(Content.Link)"
OverwriteReadOnlyFiles="true"
ContinueOnError="true"
Condition="'%(Content.Link)' != ''" />
</Target>
</Project>
Unfortunetely it doesn't work. I tried installing the MSBuild.WebApplication.CopyContentLinkedFiles NuGet package, but it didn't help.
I tried setting Copy to output directory property to Always which make them present in the build:
However scripts were still missing after launching the app from VS:
How can I make this work? I'm looking for a simplest solution possible.
Your setup potentially will work for publish scenarios but for development environment it won't - the wwwroot folder from the project root (i.e. WebApp1\wwwroot and WebApp2\wwwroot) is used to serve the static files, so you need to copy the shared file there on build (possibly exclude it from git also for convenience).

Appsettings.json get string with two programs running

I'm using run and debugging from VS Code, but when i run both projects API and MVC, give me error.
An exception of type 'System.ArgumentNullException' occurred in Microsoft.EntityFrameworkCore.SqlServer.dll but was not handled in user code: 'Value cannot be null.'
My code:
options.UseSqlServer(Configuration["Data:UCASAppDatabase:ConnectionString"]));
This happen after i run both projects using debug, but if i create appsettings outside API work, but what i want is work with appsettings inside API.
How i get string from appsettings.json, without creating new appsettings.json?
It's generally best to keep them separate, but if you really want to use just one, you should be able to add the appsettings.json file as a linked item in the project that doesn't contain the physical file. Use add => existing item, select "Add as Link" from the Add drop-down and select the file(s) you want to add. Make sure their build action is Content + "Copy if Newer" and you should be good to go. You might consider making a solution folder and putting shared resources there so it's more apparent that you have shared resources.
Edit:
You should be able to manually add if VS Code doesn't have a way through the UI.
Editing the .csproj file and add the content files you need:
<ItemGroup>
<Content Include="..\Root\appsettings.json" Link="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

XUnit .Net Core How to get local settings inside Test project

I have a XUnit project for End2End test for my Api Project.
Inside the Unit project: MyApi.E2E.Test
under its root folder, I have a setting file:
e2e-local-settings.json
Now I have a File called: MyWebApplicationFactory
public class MyWebApplicationFactory<TStartUp>: WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
........code here.......
}
}
How can I load the setting json file under the TEST project.
I have read this one: https://stackoverflow.com/a/47591692/601862
But it does not load from the Test Project, instead it loads from the Api project.
The reason for it not finding it is because configuration files are expected to be in the application running directory. In your .csproj file, you would need to add a <Content> tag so that it is copied to the output directory.
<ItemGroup>
<Content Include="e2e-local-settings.json" CopyToOutputDirectory="PreserveNewest" Link="e2e-local-settings.json" />
</ItemGroup>
Make sure after you add this, to look at the loaded modules window in the debugger, and look at the path where your test .dll is loaded from. Look at that directory, and make sure the file exists there, if the file doesn't exist, it will fail in the way you're seeing it.

how reference file published with build action content

I have a c# project that needs to load some yaml resources to work, I have set them with "build action":"content" and "copy to Output directory":"Copy if newer"
To load them I use simply a relative path, and everything works inside the project.
I realized xunit project that loads the library and everything still works fine.
Now I released the library on nuget and I am trying to reference on an Asp.Net Core, but when I try to load my files, the application tries to find them in the wrong folder:
The files are searched in relative path from the root asp.net project, but files are in C:\Users\[name]\.nuget\packages\[pakage name]\[version]\content
So I am wondering how can I get the "content" folder of the assembly in C#?
UPDATE: I TRY TO EXPLAIN BETTER
I have a visual studio solution, we call it foo.sln and a C# project that we call foo.csproj
The project is a netstandard 2.0 library and it's built to be consumed by other applications: cli, asp.net, core, wpf, etc...
The library is built to be multiplatform, so could run on Windows, Mac and on Linux
Inside the root of foo project there is a folder we call it YamlDefinitions
Inside of that folder we have a lot of .yaml files that needs to be loaded and parsed by my foo library.
So foo.csproj has something like:
<Content Include="YamlDefinitions\Definition1.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition2.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition3.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition4.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
These files are immutable, so I load them as content instead as resource
Now inside the c# code of my foo library, I have:
var filePaths = Directory.GetFiles("YamlDefinitions", "*.yaml", SearchOption.TopDirectoryOnly)
foreach (var filePath in filePaths)
{
using (var reader = new StreamReader(filePath))
{
// Load the stream
var yamlStream = new YamlStream();
yamlStream.Load(reader);
yaml = yamlStream.Documents.FirstOrDefault();
}
}
That code search, loads and parse all yaml files that can find in the specified folder.
Everything seems ok, so now to test I create an xunit prject inside the foo.sln, we call it footest.csproj
Now I reference foo.csproj inside footest.csproj
<ProjectReference Include="..\Foo\foo.csproj" />
All tests passed so I pack the library and publish the nuget package: foo.nuget
Now I want try to use my nuget package, so I create a new console application with Net Core 2.2, we call it MyConsoleApp.csproj
I install my nuget package foo.nuget:
<PackageReference Include="Foo" Version="1.0.0"/>
the package is installed and all yaml files are placed in
C:\Users\UserName\\.nuget\packages\Foo\1.0.0\content\YamlDefinitions
and in
C:\Users\UserName\\.nuget\packages\Foo\1.0.0\contentFiles\any\netstandard2.0\YamlDefinitions
The files are also visible inside MyConsoleApp.csproj as linked files, but they are not physically present in the project.
Now I launch my MyConsoleApp.exe, and I get an error, because it's unable to find these yaml files, because the application tries to load them in the same path as MyConsoleApp.exe
Workaround: from visual studio I select all yaml files that are linked inside MyConsoleApp.csproj and I set as CopyIfNewer
Now inside cproj visual studio adds these lines of codes:
<Content Include="C:\Users\User\.nuget\packages\Foo\1.0.0\contentFiles\any\netstandard2.0\YamlDefinitions\Definition1.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
I run again MyConsoleApp.exe and everything works.
This workaround is bad because the end user should be able to use the nuget library without specifying manually to copy files.
If I release a new version of my library that contains new definitions, the end user should not be aware that these must be included in the project.
Anyway, there is a bigger problem:
I create a new ASP.NET Core 2.2 MVC Application, we call it MyWebApp.csproj
I install Foo.nuget and I try to use it.
I set manually to copy all Yaml definitions in output folder, and when I build they are automatically copied in MyWebApp\bin\Release\netcoreapp2.2\YamlDefinitions
I launch the web app and I get again an error, because my foo libray tried to find files in MyWebApp\YamlDefinitions, but files are in bin folder, so nothing works.
How can I fix my library and and publish as nuget in a way that all consumer applications can use it?
I can't find a C# function that retrieves the nuget folder where content files are stored and I doubt that could exist, but I found this working approach:
In foo.csproj file you need to specify that each file should be copied in output folder, this can be done with:
<Content Include="YamlDefinitions\Definition1.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
You need to add PackageCopyToOutput to make working with nuget, unfortunately, this can't be done from visual studio UI and you have to edit .csproj manually.
In C# you have to use an absolute path because relative path is not the same in all kind of application (in a .NET cli is different from ASP.NET)
So you have to use a code like this:
var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "YamlDefinitions");
var filePaths = Directory.GetFiles(directory, "*.yaml", SearchOption.TopDirectoryOnly)
Where AppDomain.CurrentDomain.BaseDirectory return the output directory where content files are copied

AWS Lambda Serverless Application embedded resource

I have created a WebApi project and deployed this as a serverless application to AWS Lambda. It all works fine except that for one method, I need to read from a file. I can see that this file is deployed as it's in the zip file that gets pushed up but for some reason, when I come to read from it in the code, it can't find it.
I've tried both embedded resource and content for build action but neither seem to work. Is there something in AWS that needs configuring so that my serverless application can access local files?
For anyone that needs more detail. Add your embedded files into your .csproj file as below (resources is your folder, note the "resources\" in .csproj and "resources/" in .cs):
<ItemGroup>
<Content Include="resources\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
In your .cs file, to get the file path:
var path = Path.Combine(Directory.GetCurrentDirectory(), "resources/example.txt");

Categories