Sdk: Consider adding setting a 'project directory' environment variable in dotnet-run

Created on 2 Jun 2016  路  8Comments  路  Source: dotnet/sdk

It looks like some of the ASP.NET-specific stuff used to support an ASPNET_APPLICATIONBASE environment variable in order to allow a web application to automatically determine its 'base path' correctly whether it was running from the context of a project with dotnet-run (variable set) or from the context of a set of published outputs (no variable set.) It seems that the Visual Studio tooling sets this variable since some point in the past, at least to support RC1 projects.

I don't know whether this kind of situation will really apply to anything other than ASP.NET web applications, at least in the overwhelming majority of cases, but I feel like dotnet-run should be responsible for setting one or more environment variables like DOTNET_PROJECTDIRECTORY that running applications could use to be context-aware.

Related:

https://github.com/dotnet/cli/pull/1382
https://github.com/aspnet/Hosting/issues/651

question

Most helpful comment

Note that you can add this to your csproj file inside a <PropertyGroup> to force dotnet run to use the project's directory:

<RunWorkingDirectory>$(MSBuildThisFileDirectory)</RunWorkingDirectory>

Setting RunWorkingDirectory as environment variable will also make MSBuild pick it up.

All 8 comments

There has not, thus far, been an intention to differentiate run from direct execution. What scenario does the current behavior block?

/cc @blackdwarf @davidfowl

@piotrpMSFT I don't know that it would _have to be_ a distinction between run and direct execution if that bit of data could be supplied by build in the exe.config or whatever. Then other tools for publishing and deployment and whatever else could manipulate the value as needed for their use cases.

That bit of data would just allow the running application to know where its 'stuff' is without relying on the user running the application from that exact directory.

What scenario does the current behavior block?

With RC2, you can dotnet run -p ./path/to/my/project but it's not going to do any good if that project needs to access a config.json or similar file in its folder.

I have the same problem. I am trying to dotnet run -p ./path/to/my/project

In main, I have

new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())

and then in Startup I have

new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddUserSecrets()

This results in:

Unhandled Exception: System.InvalidOperationException: Unable to locate a project.json at '{CurrentDirectory}'.
   at Microsoft.Extensions.Configuration.UserSecrets.PathHelper.GetSecretsPath(IFileProvider provider)

Since dotnet run -p doesn't change the current working directory, the base path point to current and not to ./path/to/my/project. And AddUserSecrets is expecting to find a project.json at the basepath and failing to do so.

Ran into another scenario -- converting a Windows Service to run on .NET Core. Directory.GetCurrentDirectory() is not good for when the service is deployed and running. In that case I would want to use ApplicationBase, which of course thrashes the local development scenario.

My current workaround:

            var configBasePath = Directory.GetCurrentDirectory();

            if (!File.Exists(Path.Combine(configBasePath, "config.json")))
            {
                configBasePath = AppDomain.CurrentDomain.BaseDirectory;
            }

            var configuration = new ConfigurationBuilder()
                    .SetBasePath(configBasePath)
                    .AddJsonFile("config.json")
                    .Build();

As of .NET Core SDK 1.0 rc4 build 004771.

My dirty hack until I figure out a better way:

Project Structure:

src/
  Web/
    bin/
        Debug/
            netcoreapp1.0/
            ...
    ...
    appsettings.json
    Program.cs
    Startup.cs
    Web.csproj
MyApp.sln

Program.cs

var configBasePath = Directory.GetCurrentDirectory();

if (!File.Exists(Path.Combine(configBasePath, "appsettings.json")))
{
    configBasePath = Directory.GetParent(System.AppContext.BaseDirectory).Parent.Parent.FullName;
}

VS Code Terminal

Current working directory is the solution root:

PS C:\Code\MyApp> dir


    Directory: C:\Code\MyApp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        2/22/2017  11:23 PM                src
-a----        2/22/2017  11:32 PM           1914 MyApp.sln

Build solution and run the project:

PS C:\Code\MyApp> dotnet build .\MyApp.sln; dotnet run --project .\src\Web\Web.csproj

Note that you can add this to your csproj file inside a <PropertyGroup> to force dotnet run to use the project's directory:

<RunWorkingDirectory>$(MSBuildThisFileDirectory)</RunWorkingDirectory>

Setting RunWorkingDirectory as environment variable will also make MSBuild pick it up.

@dasMulli will have to see how convenient/inconvenient that is before a final verdict, but for now, FERRIS BUELLER YOU'RE MY HERO

Was this page helpful?
0 / 5 - 0 ratings