Virtual directory inside of ASP.NET Core app in IIS

Viewed 34369

We have an application using ASP.NET Core 1.0 RC1 and hosted on IIS. It works fine. Now we have static content, that is available on a file share and should be accessible from the application.

Before ASP.NET 5, we added a virtual directory in IIS and could access the shared content easily. With our hosted ASP.NET 5 application, this unfortunately doesn't seem to work. We just get a 404 back when trying to access the static content.

Our application is using app.UseIISPlatformHandler() and app.UseStaticFiles(), but this doesn't work. We discovered that we could use app.UseFileServer() with custom FileServerOptions to get the desired behavior, but we are curious if it's also possible with the normal "old" way of adding a virtual directory in IIS.

6 Answers

I have found a blog which I think must have been written by the OP.

The upshot is not to use a virtual directory in IIS at all but rather map your path in Startup.cs to the physical server directory. I hope the OP does not mind that I have pasted the blog below, but it helped me when I first encountered this problem today.

Source: https://www.jauernig-it.de/asp-net-coreiis-serving-content-from-a-file-share/

There are situations, when you want to serve static content with your application, that is not part of it, e.g. because it exists on a common file share. Website content, that is managed by a business division, could be such a use case. In ASP.NET before Core, this was no problem in IIS: just create a virtual directory within your IIS website and point it to the file share.

Unfortunately, with ASP.NET Core, this approach isn’t working any longer. If you add a virtual directory to your ASP.NET Core application in IIS, it isn’t recognized and a 404 is returned. It’s because of DNX/Kestrel, which is running beneath IIS (using the HttpPlatformHandler module) and to which IIS only brokers the requests. Kestrel doesn’t know anything of virtual directories from IIS. And because ASP.NET Core applications are independent from IIS and could also be run without it (e.g. running Kestrel standalone), that should be considered as a good thing.

But now we need another solution for our problem… fortunately, ASP.NET Core gives us a programmatic interface to serve files from anywhere. Just add the following code to your Startup.cs Configure() method:

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(@"\\server\path"),
    RequestPath = new PathString("/MyPath"),
    EnableDirectoryBrowsing = false
});

What this essentially does, is adding a file server to a physical server path, that is then available on a certain request path, in this case with directory browsing disabled. You are also able to serve from a path relative to your application, using new PhysicalFileProvider(env.WebRootPath + "\path") (given env is of type IHostingEnvironment as parameter of Configure()). Voila, that’s it. There is no need to add a „virtual directory“ in IIS, this stuff is deprecated and a thing of the past. For me, this is a good thing, because we get more independent of the whole IIS…

I encountered this problem today, and finally managed to fix it. The trick (for me, probably not for everyone) is making sure the aspNetCore handler is disabled in the sub-application and enabled in the main (ASP.NET Core) application.

My ASP.NET Core app has a basic Web.config

<configuration>
  <system.webServer>
    <handlers>
        <add name="aspNetCore" path="*" verb="*" type="" modules="AspNetCoreModule" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\bin\Debug\netcoreapp2.0\myapp.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>

and the application added as a sub-application in IIS has

<configuration>
  <!-- removed -->
  <system.webServer>
      <handlers>
          <remove name="aspNetCore" />
       </handlers>
  </system.webServer>
</configuration>

I know its a question with 1,8 year, but if someone needs to resolve the same problem, try to use this:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot", "images")),
        RequestPath = new PathString("/MyImages")
    });
}

Is perfectly possible to change parameters of PhysicalFileProvider to any local or shared folder, and with this serve a file.

Doing that in this way is not SECURITY recommended. But, for study propose, its acceptable.

The static file module provides no authorization checks. Any files served by it, including those under wwwroot are publicly available. To serve files based on authorization: Store them outside of wwwroot and any directory accessible to the static file middleware and Serve them through a controller action, returning a FileResult where authorization is applied.

In Microsoft's Asp.Net documentations we can find more complete information to help with this issue.

Check this link: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files

.Net Core has very limited support for IIS virtual directories. As a workaround, you can use Microsoft.Web.Administration to get list of a Site ("Default Web Site") virtual directories. Replace Path with PhysicalPath to locate the resources

Create a .NetStandard lib project (>= 1.6.0), and use this example

Related