Cách lấy thư mục gốc của dự án trong lõi asp.net. Directory.GetCurrentDirectory () dường như không hoạt động chính xác trên máy mac


82

Dự án của tôi có cấu trúc thư mục phù hợp với:

  • Dự án,
  • Dữ liệu dự án
  • Dự án / Động cơ
  • Dự án / Máy chủ
  • dự án / front-end

Trong máy chủ (chạy trong thư mục Dự án / Máy chủ), tôi tham chiếu đến thư mục như sau:

var rootFolder = Directory.GetCurrentDirectory();
rootFolder = rootFolder.Substring(0,
            rootFolder.IndexOf(@"\Project\", StringComparison.Ordinal) + @"\Project\".Length);
PathToData = Path.GetFullPath(Path.Combine(rootFolder, "Data"));

var Parser = Parser();
var d = new FileStream(Path.Combine(PathToData, $"{dataFileName}.txt"), FileMode.Open);
var fs = new StreamReader(d, Encoding.UTF8);

Trên máy tính Windows của tôi, mã này hoạt động tốt vì được Directory.GetCurrentDirectory()đưa vào thư mục hiện tại và

rootFolder.Substring(0, rootFolder.IndexOf(@"\Project\", StringComparison.Ordinal) + @"\Project\".Length); 

lấy cho tôi thư mục gốc của dự án (không phải thư mục bin hoặc gỡ lỗi). Nhưng khi tôi chạy nó trên máy mac, nó nhận được " Directory.GetCurrentDirectory()" gửi cho tôi đến / usr // [cái gì đó khác]. Nó không tham chiếu đến thư mục chứa dự án của tôi.

Cách chính xác để tìm đường dẫn tương đối trong dự án của tôi là gì? Tôi nên lưu trữ thư mục dữ liệu ở đâu để có thể dễ dàng truy cập vào tất cả các dự án con trong giải pháp - cụ thể là đối với dự án máy chủ kestrel? Tôi không muốn phải lưu trữ nó trong thư mục wwwroot vì thư mục dữ liệu được duy trì bởi một thành viên khác trong nhóm và tôi chỉ muốn truy cập phiên bản mới nhất. Những lựa chọn của tôi là gì?

Câu trả lời:


72

Tùy thuộc vào vị trí bạn đang ở trong đường ống kestrel - nếu bạn có quyền truy cập vào IConfiguration(phương thức Startup.cskhởi tạo ) hoặc IWebHostEnvironment( trước đâyIHostingEnvironment ), bạn có thể đưa nó vào phương thức khởi IWebHostEnvironmenttạo của mình hoặc chỉ yêu cầu khóa từ cấu hình.

Inject IWebHostEnvironmentin Startup.csConstructor

public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
     var contentRoot = env.ContentRootPath;
}

Sử dụng IConfiguration trong Startup.cs Constructor

public Startup(IConfiguration configuration)
{
     var contentRoot = configuration.GetValue<string>(WebHostDefaults.ContentRootKey);
}

bạn có thể đưa IConfiguration vào bộ điều khiển và nhận được những gì bạn cần từ đó. đúng?
Yehuda Makarov

1
làm cách nào chúng ta có thể truy cập contentRoot trong Startup?
Cihan Küsmez

3
IHostingEnvironment bây giờ đã lỗi thời int Core, và thay thế bằng IWebHostEnvironment
Antonio Rodríguez

1
@ AntonioRodríguez - được cập nhật để phản ánh, IWebHostEnvironmentdụng cụ IHostEnvironment- tham khảo - IHostingEnvironmentđã ngừng hoạt động
SliverNinja - MSFT

61

Làm việc trên .Net Core 2.2 và 3.0 tính đến thời điểm hiện tại.

Để lấy thư mục gốc của dự án trong Bộ điều khiển:

  • Tạo thuộc tính cho môi trường lưu trữ

    private readonly IHostingEnvironment _hostingEnvironment;
    
  • Thêm Microsoft.AspNetCore.Hosting vào bộ điều khiển của bạn

    using Microsoft.AspNetCore.Hosting;
    
  • Đăng ký dịch vụ trong phương thức khởi tạo

    public HomeController(IHostingEnvironment hostingEnvironment) {
        _hostingEnvironment = hostingEnvironment;
    }
    
  • Bây giờ, để lấy đường dẫn gốc của dự án

    string projectRootPath = _hostingEnvironment.ContentRootPath;
    

Để lấy đường dẫn " wwwroot ", hãy sử dụng

_hostingEnvironment.WebRootPath

2
Đây tốt tiếp cận làm việc cho Net Lõi 2.2 cũng
Magnus Wallstrom

1
như muốn lấy đường dẫn tệp trong chế độ phát triển có nghĩa là trong khi chạy dự án từ studio trực quan "_hostingEnosystem.WebRootPath" và "hostingEnosystem.ContentRootPath" đều trả về giá trị rỗng. những gì tôi nên làm gì để có được những đường dẫn tập tin
saifullah malik

@maliksaifullah kiểm tra xem bạn wwwrootcó ở đó trong dự án không và nó không trống.
StefanJM

@maliksaifullah Bạn có thể chỉ cho tôi bộ điều khiển của bạn nơi bạn đang cố lấy đường dẫn không?
StefanJM

@maliksaifullah Bạn có đang đăng ký dịch vụ trong bộ điều khiển không? Tôi không nghĩ rằng IHostingEvironmentnó được tiêm bằng cách sử dụng tiêm phụ thuộc ở đây và đó là vấn đề.
StefanJM

21

Trong một số trường hợp _hostingEnvironment.ContentRootPathSystem.IO.Directory.GetCurrentDirectory()mục tiêu đến thư mục nguồn. Đây là lỗi về nó.

Giải pháp được đề xuất ở đó đã giúp tôi

Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

Tất cả ứng dụng .NET Core là một Bảng điều khiển.
harveyt

Trong ứng dụng Core, điều này trả về "... \ bin \ Debug \ netcoreapp \" và không phải là thư mục dự án gốc như mong đợi.
Roberto

@Roberto Thư mục dự án gốc cho các ứng dụng lõi mạng sẽ không được trả lại. Đây là một hành vi đúng.
aleha

20

Như đã trả lời trước đây (và đã rút lại). Để lấy thư mục cơ sở , như trong vị trí của assembly đang chạy, không sử dụng Directory.GetCurrentDirectory (), thay vào đó lấy nó từ IHostingEnosystem.ContentRootPath.

private IHostingEnvironment _hostingEnvironment;
    private string projectRootFolder;
    public Program(IHostingEnvironment env)
    {
        _hostingEnvironment = env;
        projectRootFolder = env.ContentRootPath.Substring(0,
            env.ContentRootPath.LastIndexOf(@"\ProjectRoot\", StringComparison.Ordinal) + @"\ProjectRoot\".Length);
    }

Tuy nhiên, tôi đã mắc phải một lỗi bổ sung: Tôi đã đặt Thư mục ContentRoot thành Directory.GetCurrentDirectory () khi khởi động làm xói mòn giá trị mặc định mà tôi rất mong muốn! Ở đây tôi đã nhận xét dòng vi phạm:

 public static void Main(string[] args)
    {
        var host = new WebHostBuilder().UseKestrel()
           // .UseContentRoot(Directory.GetCurrentDirectory()) //<== The mistake
            .UseIISIntegration()
            .UseStartup<Program>()
            .Build();
        host.Run();
    }

Bây giờ nó chạy chính xác - bây giờ tôi có thể điều hướng đến các thư mục con của các dự án gốc của tôi bằng:

var pathToData = Path.GetFullPath(Path.Combine(projectRootFolder, "data"));

Tôi đã nhận ra sai lầm của mình khi đọc câu trả lời của BaseDirectory so với Current Directory và @CodeNotFound (đã được rút lại vì nó không hoạt động vì lỗi ở trên), về cơ bản có thể tìm thấy ở đây: Lấy đường dẫn WebRoot và Đường dẫn gốc nội dung trong Asp.net Cốt lõi


7
FYI nếu bạn đang tự hỏi làm thế nào để có được IHostingEnosystem trong lớp Startup: hãy thêm nó làm đối số hàm tạo.
Endy Tjahjono

16

Hãy thử xem tại đây: Cách tốt nhất để lấy đường dẫn thư mục ứng dụng

Để trích dẫn từ đó:

System.IO.Directory.GetCurrentDirectory()trả về thư mục hiện tại, có thể có hoặc không phải là thư mục chứa ứng dụng. Tương tự với Environment.CurrentDirectory. Trong trường hợp bạn đang sử dụng tệp này trong tệp DLL, nó sẽ trả về đường dẫn nơi quá trình đang chạy (điều này đặc biệt đúng trong ASP.NET).


15

Nếu bạn đang sử dụng ASP.NET MVC Core 3 hoặc mới hơn, IHostingEnvironmentđã không được dùng nữa và được thay thế bằngIWebHostEnvironment

public Startup(IWebHostEnvironment webHostEnvironment)
{
    var webRootPath = webHostEnvironment.WebRootPath;
}

9

Tôi đã giải quyết vấn đề với mã này:

using System.IO;

var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.Substring(0, Assembly.GetEntryAssembly().Location.IndexOf("bin\\")))

Một câu trả lời thực sự dễ hiểu và hiệu quả. cảm ơn!
BMills

1

Nếu điều đó có thể hữu ích cho bất kỳ ai, trong tệp cshtml.cs của Razor Page, đây là cách lấy nó: thêm một IHostEnvironment hostEnvironmenttham số vào hàm tạo và nó sẽ được đưa vào tự động:

public class IndexModel : PageModel
{
    private readonly ILogger<IndexModel> _logger;
    private readonly IHostEnvironment _hostEnvironment;

    public IndexModel(ILogger<IndexModel> logger, IHostEnvironment hostEnvironment)
    {
        _logger = logger;
        _hostEnvironment = hostEnvironment; // has ContentRootPath property
    }

    public void OnGet()
    {

    }
}

Tái bút: IHostEnvironmentlà trong Microsoft.Extensions.Hostingkhông gian tên, trong Microsoft.Extensions.Hosting.Abstractions.dll... thật là một mớ hỗn độn!


0

Có vẻ như IHostingEnosystem đã được thay thế bằng IHostEnosystem (và một vài cái khác). Bạn sẽ có thể thay đổi kiểu giao diện trong mã của mình và mọi thứ sẽ hoạt động như trước đây :-)

Bạn có thể tìm thêm thông tin về những thay đổi tại liên kết này trên GitHub https://github.com/aspnet/AspNetCore/issues/7749

CHỈNH SỬA Ngoài ra còn có một giao diện bổ sung IWebHostEnosystem có thể được sử dụng trong các ứng dụng ASP.NET Core. Điều này có sẵn trong không gian tên Microsoft.AspNetCore.Hosting.

Tham khảo: https://stackoverflow.com/a/55602187/932448

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.