Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing class library's content files #18159

Open
skyflyer opened this issue Jun 8, 2021 · 8 comments
Open

Accessing class library's content files #18159

skyflyer opened this issue Jun 8, 2021 · 8 comments
Milestone

Comments

@skyflyer
Copy link

skyflyer commented Jun 8, 2021

What is the correct approach in accessing a class library's (not Razor class library!) content files?

For the purpose of this discussion and demonstration, let's have a class library C1 and a simple web app called Runner.

The C1 library contains a file Assets/template.txt that it uses at runtime. This could also be some other binary file that the library uses for its functionality, but let's say that this is not a static web asset (for which the solution exists in the Razor class library).

This library is used in the project Runner. Since the library defines that the Assets/template.txt is copied to output directory and is copied to publish directory, it is possible to access the Assets/template.txt by using IHostEnviornment.ContentRootPath and append Assets/template.txt to it. This only works if you dontet publish the Runner application and run the published binary, but does not work if you dotnet run the runner.

The reason, as I understand, is there is only one IHostEnvironment and so there can be only one ContentRootPath... so accessing the files in the individual class library can be done by using a "workaround":

string assemblyPath = Assembly.GetExecutingAssembly().Location;
string binFolder = Path.GetDirectoryName(assemblyPath)!;

var path = Path.Join(binFolder, "Assets", "template.txt");

The question here is, if this is the correct way to access to these files or is there a better way?

The runnable short demo is provided here: demo.zip

If you dontet publish -o out and cd out and dotnet Runner.dll, you will se that it is working, since Assets folder will be present there. If you just dotnet run it, the Assets/template.txt will not be resolved correctly.

I know there is also the option of EmbeddedResources, but that breaks some other library I'm using which wants to access certain files via regular file system APIs.

@Pilchie
Copy link
Member

Pilchie commented Jun 8, 2021

This is partially an SDK issue question, so also tagging @dsplaisted.

@Pilchie Pilchie transferred this issue from dotnet/aspnetcore Jun 8, 2021
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Request triage from a team member label Jun 8, 2021
@dsplaisted
Copy link
Member

The SDK copies the content file from the library project to the output folder for the runner. I think the issue is that when you build a web app but don't publish it, the ContentRootPath is the source root of the project file, not its output path. Is this correct?

If so, I'm not sure what the solution is. Maybe web projects should have a setting where they use the output folder instead of the project file folder (ie skipping the optimization where they don't need to copy content files to the output folder)?

@Pilchie
Copy link
Member

Pilchie commented Jun 9, 2021

Ah, interesting point. Tagging @pranavkm and @javiercn for their thoughts on this.

@skyflyer
Copy link
Author

skyflyer commented Jun 9, 2021

@Pilchie, @dsplaisted - you're correct that it is an SDK issue, sorry for putting it in the wrong place;

The main issue is that the behaviour between dotnet Runner.dll and dotnet run is different, which, IMHO, should not be the case.

The ContentRootPath, as I understand it, should point to the "content" path location and the question for the discussion is how to handle this with dotnet run which has a different bin location and content location. WebRootPath for asp.net core projects is a "similar" issue and is handled.

Perhaps we should first answer the question regarding "bin path" (i.e. debug/net5.0 when dotnet run-ing vs published path): is the ContentRootPath different from "bin path"? Or should they be the same?

@dsplaisted
Copy link
Member

@skyflyer Don't worry too much about filing in the exact right repo, we have a lot of them and it's not always obvious where the root cause of an issue is. We'll try to move them as appropriate. :-)

@javiercn
Copy link
Member

javiercn commented Jun 9, 2021

ContentRootPath points to the project folder when you do dotnet run. If you are not using static web assets (which as you mentions takes care of this) the best way to do this is to make sure the assets end up in the build output folder and to resolve them relative to the app entry point assembly location.

@skyflyer
Copy link
Author

skyflyer commented Jun 9, 2021

So, @javiercn, you're essentially saying that Assembly.GetExecutingAssembly().Location is the correct approach (since it works for dotnet run as well as dotnet assembly.dll?

@wli3 wli3 removed the untriaged Request triage from a team member label Aug 6, 2021
@wli3 wli3 removed their assignment Aug 6, 2021
@wli3 wli3 added this to the Discussion milestone Aug 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants