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.
https://github.com/dotnet/cli/pull/1382
https://github.com/aspnet/Hosting/issues/651
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:
src/
Web/
bin/
Debug/
netcoreapp1.0/
...
...
appsettings.json
Program.cs
Startup.cs
Web.csproj
MyApp.sln
var configBasePath = Directory.GetCurrentDirectory();
if (!File.Exists(Path.Combine(configBasePath, "appsettings.json")))
{
configBasePath = Directory.GetParent(System.AppContext.BaseDirectory).Parent.Parent.FullName;
}
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
Most helpful comment
Note that you can add this to your csproj file inside a
<PropertyGroup>
to forcedotnet run
to use the project's directory:Setting
RunWorkingDirectory
as environment variable will also make MSBuild pick it up.