Asp.Net Implementation of virtual directory in core

Time:2021-2-3

Write on the front

Deploy now Asp.Net Core applications are no longer limited to windows IIS, but are more deployed by docker container and various reverse agents. There are also a small number of IIS deployment, IIS deployment is really fast and simple, graphical operation three under five divided by two can publish a good system. in the past Asp.Net When MVC projects are deployed, virtual directory, a function of IIS, is often used.

The virtual directory can be directly located to other paths of non project, and the path can be used as a part of the website to save the uploaded files to other drive letters or indirectly use the static files other than the project. stay Asp.Net It’s also easy to access files from virtual paths in MVC, such as Server.MapPath (“~/Upload/ liohuang.jpg “);

But in Asp.Net Core is different, it is abstracted as a “file system”, that is, fileprovider. Fileprovider is a general term for all types and corresponding objects that implement the ifileprovider interface《File system of. Net core [2]: what is fileprovider?》The article has been dialysis, here is not in the wordy bar.

The content to be solved in this article is as follows: Asp.Net How to use “virtual directory” gracefully in core applications.

Practice

First, create a new. Net core webapi empty project and deploy it on disk D. the virtual directory assumes that the physical path is on disk F. three test directories are created respectively: F / test1, f / test2 and F / test3. The corresponding files 1 / 2 / 3.jpg and 1 / 2 / 3.jpg are stored in the directories mybook.txt .

Read virtual directory file

stay Startup.ConfigureServices Inject ifileprovider:


services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\test1"));

Create a new controller and read it mybook.txt Content in

[ApiController]
 [Route("[controller]/[action]")]
 public class LioHuangController : ControllerBase
 {
  [HttpGet]
  public object GetFiles([FromServices]IFileProvider fileProvider)
  {
   var file = fileProvider.GetFileInfo("mybook.txt");
   if (file.Exists)
   {
    return ReadTxtContent(file.PhysicalPath);
   }
   return 0;
  }

  /// <summary>
  ///Read text (original address: https://www.cnblogs.com/EminemJK/p/13362368.html )
  /// </summary>
  private string ReadTxtContent(string Path)
  {
   if (!System.IO.File.Exists(Path))
   {
    return "Not found!";
   }
   using (StreamReader sr = new StreamReader(Path, Encoding.UTF8))
   {
    StringBuilder sb = new StringBuilder();
    string content;
    while ((content = sr.ReadLine()) != null)
    {
     sb.Append(content);
    }
    return sb.ToString();
   }
  }
 }

After reading the file, the interface returns the following contents:

Ifileprovider interface uses directory to organize files, and uniformly uses ifileinfo interface to represent files. Physicalpath represents the physical path of files.


public interface IFileInfo
 {
  bool Exists { get; }
  bool IsDirectory { get; }
  DateTimeOffset LastModified { get; }
  string Name { get; }
  string PhysicalPath { get; }
  Stream CreateReadStream();
 }

How to deal with multiple virtual directories? Simple, just inject multiple ifileproviders,


 services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\test1"));
   services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\test2"));
   services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\test3")); 

The code is changed to:


  public object GetFiles([FromServices] IEnumerable<IFileProvider> fileProviders)

There will be three IEnumerable < ifileprovider > fileproviders interface arrays corresponding to different directories in the order of injection. Of course, when injecting ifileprovider, you can encapsulate a layer, which will be discussed later.

In addition, some people say that they can directly read txtcontent (“F:: test1”)\ mybook.txt Is it not fragrant? Fragrance, Asp.Net The access right of the core is higher than that of the core Asp.Net Before MVC, the old version of the project is much higher. It is true that it can read files other than the project directly, but it is not suitable for direct access. Unless you have only one place to use, you can read them directly, but static files can not be accessed, just background reading. Therefore, if ifileprovider is used to constrain the code, the maintainability of the code is much higher.

Static file access

stay Startup.Configure Set the static file directory


app.UseStaticFiles(new StaticFileOptions()
   {
    FileProvider = new PhysicalFileProvider("F:\test1"),
    RequestPath = "/test"
   });;
  app.UseStaticFiles(new StaticFileOptions()
   {
    FileProvider = new PhysicalFileProvider("F:\test2"),
    RequestPath = "/test"
   });
  app.UseStaticFiles(new StaticFileOptions()
   {
    FileProvider = new PhysicalFileProvider("F:\test3"),
    RequestPath = "/test"
   });

Fileprovider is the same as above. Set the root directory of the physical path. Requestpath is the prefix of the access path. It must start with a slant bar ‘/’, and the access address prefix is: https://localhost :5001/test/。 After setting, you can access the path outside the project.

For example, when deploying IIS, you can directly ignore the setting of virtual directory in IIS. You can completely set it by injecting configuration to achieve the effect of “virtual directory”.

Simplify configuration

In order to facilitate direct use in real projects, it is necessary to set it as configurable:

stay appsettings.json Setting in:

{
 "Logging": {
 "LogLevel": {
  "Default": "Information",
  "Microsoft": "Warning",
  "Microsoft.Hosting.Lifetime": "Information"
 }
 },
 "AllowedHosts": "*",

 "VirtualPath": [
 {
  "Realpath": "F: \ \ test1", // real path
  "RequestPath": "/test",
  "Alias": "first"
 },
 {
  "Realpath": "F: \ \ test2", // real path
  "RequestPath": "/test",
  "Alias": "second"
 },
 {
  "Realpath": "F: \ \ test3", // real path
  "RequestPath": "/test",
  "Alias": "third"
 }
 ]
}

Create the corresponding entity mapping:


public class VirtualPathConfig
 {
  public List<PathContent> VirtualPath { get; set; }
 }

 public class PathContent
 {
  public string RealPath { get; set; }

  public string RequestPath { get; set; }

  public string Alias { get; set; }
 }

Encapsulate a layer on the physicalfileprovider and add an alias for easy access

public class MyFileProvider : PhysicalFileProvider
  {
    public MyFileProvider(string root, string alias) : base(root)
    {
      this.Alias = alias;
    }

    public MyFileProvider(string root, Microsoft.Extensions.FileProviders.Physical.ExclusionFilters filters, string alias) : base(root, filters)
    {
      this.Alias = alias;
    }

    /// <summary>
    ///Alias
    /// </summary>
    public string Alias { get; set; }
  }

adjustment Startup.ConfigureServices and Startup.Configure :


public void ConfigureServices(IServiceCollection services)
    {
      services.AddControllers();
      services.Configure<VirtualPathConfig>(Configuration);

      var config = Configuration.Get<VirtualPathConfig>().VirtualPath;
      config.ForEach(f => 
      {
        services.AddSingleton(new MyFileProvider(f.RealPath,f.Alias));
      });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      var config = Configuration.Get<VirtualPathConfig>().VirtualPath;
      config.ForEach(f =>
      {
        app.UseStaticFiles(new StaticFileOptions()
        {
          FileProvider = new PhysicalFileProvider(f.RealPath),
          RequestPath =f.RequestPath
        });
      });
       
      app.UseRouting();
      app.UseAuthorization();
      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers();
      });
    }

Finally, adjust the call mode.


[HttpGet]
    public object GetFiles([FromServices] IEnumerable<MyFileProvider> fileProviders)
    {
      var file = fileProviders.FirstOrDefault(x=>x.Alias=="first").GetFileInfo("mybook.txt");
      if (file.Exists)
      {
        return ReadTxtContent(file.PhysicalPath);
      }
      return 0;
    }

last

The abstraction of physical file system is realized by physical fileprovider. With the characteristics of ifileprovider, the function of lightweight “cloud disk” can be extended instead of just realizing IIS virtual directory function. Done. No overtime tonight!

This is about Asp.Net This is the article about the implementation of “virtual directory” in core, and more about it Asp.Net Core virtual directory content, please search previous articles of developer or continue to browse the following related articles. I hope you can support developer more in the future!

Recommended Today

Review of SQL Sever basic command

catalogue preface Installation of virtual machine Commands and operations Basic command syntax Case sensitive SQL keyword and function name Column and Index Names alias Too long to see? Space Database connection Connection of SSMS Connection of command line Database operation establish delete constraint integrity constraint Common constraints NOT NULL UNIQUE PRIMARY KEY FOREIGN KEY DEFAULT […]