I am trying to download a .html file that I placed in the wwwroot.
This is the function:
public FileResult Download()
{
var file = Path.Combine(System.IO.Directory.GetCurrentDirectory(),"EmailTemplate","base.html");
var x = System.IO.File.Exists(file);
var result = File(file, MediaTypeNames.Text.Html);
return result;
}
I tried to check if the file exists but it returns false. The file variable shows the path to the file which is:
wwwroot\EmailTemplate\base.html
I'm unsure of what else I need to do.
EDIT:
app.UseStaticFiles(
new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "EmailTemplate")),
RequestPath = "/EmailTemplate"
}
);
This is what I added to my Startup.cs
Make sure you have app.UseStaticFiles(); in your Configure method in the Startup file.
In your controllers you can inject an IHostingEnvironment interface and use it to retrieve your wwwroot path like:
_hostingEnvironment.WebRootPath;
Related
Introduction
I'm configuring MIMEs for static files as usual, something like this (and that works fine, keep reading so you get to the actual question):
var defaultStaticFileProvider = new PhysicalFileProvider(Path.Combine(webHostEnvironment.ContentRootPath, "content"));
var contentTypeProvider = new FileExtensionContentTypeProvider();
var defaultStaticFilesRequestPath = "/content";
// This serves static files from the 'content' directory.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = defaultStaticFileProvider,
ServeUnknownFileTypes = false,
RequestPath = defaultStaticFilesRequestPath,
ContentTypeProvider = contentTypeProvider
});
The previous code is mapping the .json extension to application/json by default. Works fine.
Question
What I want is to change that mapping to application/manifest+json but only for one file: manifest.json
So, I tried to add another configuration like this (not working):
// Add custom options for manifest.json only.
var manifestContentTypeProvider = new FileExtensionContentTypeProvider();
manifestContentTypeProvider.Mappings.Clear();
manifestContentTypeProvider.Mappings.Add(".json", "application/manifest+json");
var manifestStaticFileProvider = new PhysicalFileProvider(Path.Combine(webHostEnvironment.ContentRootPath, "content/en/app"));
var manifestStaticFileRequestPath = "/content/en/app/manifest.json";
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = manifestStaticFileProvider,
ServeUnknownFileTypes = false,
RequestPath = manifestStaticFileRequestPath,
ContentTypeProvider = manifestContentTypeProvider
});
Just to clarify, I have added the above code right after the previous one.
Hope the question is clear enough, I'll be checking for comments proposing editing tips to make it better anyways.
The StaticFileOptions class has an OnPrepareResponse property to which you can assign an Action in order to change the HTTP response headers.
From the documentation
Called after the status code and headers have been set, but before the body has been written. This can be used to add or change the response headers.
In that Action you check for the manifest.json file and set/change the content-type header accordingly. That action has an StaticFileResponseContext input argument with access to the HttpContext and File.
var options = new StaticFileOptions
{
OnPrepareResponse = staticFileResponseContext =>
{
var httpContext = staticFileResponseContext.Context;
// Request path check:
if (httpContext.Request.Path.Equals("/content/en/app/manifest.json", StringComparison.OrdinalIgnoreCase))
// or file name only check via:
// if (staticFileResponseContext.File.Name.Equals("manifest.json", StringComparison.OrdinalIgnoreCase))
{
httpContext.Response.ContentType = "application/manifest+json"
}
},
// Your other custom configuration
FileProvider = defaultStaticFileProvider,
ServeUnknownFileTypes = false,
RequestPath = defaultStaticFilesRequestPath
};
app.UseStaticFiles(options);
ASP.NET Core hapily serves up files from the wwwroot folder based on the mime type of the file. But how do I get it serve up a file with no extension?
As an example, Apple require that you have an endpoint in your app /apple-app-site-association for some app-intergration. If you add a text file called apple-app-site-association into your wwwroot it won't work.
Some things I've tried:
1) Provide a mapping for when there's no extension:
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[""] = "text/plain";
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = provider
});
2) Adding an app rewrite:
var options = new RewriteOptions()
.AddRewrite("^apple-app-site-association","/apple-app-site-association.txt", false)
Neither work, the only thing that does work is a .AddRedirect which I'd rather not use if possible.
Adding an alternative solution. You have to set ServeUnknownFileTypes to true and after that set the default content type.
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "text/plain"
});
Rather than fighting with static files, I think you'd be better off just creating a controller for it:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using System.IO;
namespace MyApp.Controllers {
[Route("apple-app-site-association")]
public class AppleController : Controller {
private IHostingEnvironment _hostingEnvironment;
public AppleController(IHostingEnvironment environment) {
_hostingEnvironment = environment;
}
[HttpGet]
public async Task<IActionResult> Index() {
return Content(
await File.ReadAllTextAsync(Path.Combine(_hostingEnvironment.WebRootPath, "apple-app-site-association")),
"text/plain"
);
}
}
}
This assumes your apple-app-site-association file is in your wwwroot folder.
An easier option may be to put a file with a proper extension on the server, and then use URL rewrite as follows.
app.UseRewriter(new RewriteOptions()
.AddRewrite("(.*)/apple-app-site-association", "$1/apple-app-site-association.json", true));
I think the easiest way is to add the apple-app-site-association file in a .well-known folder in the root folder of the application as described here: [https://developer.apple.com/documentation/safariservices/supporting_associated_domains] and then allow access to it from your code, like this (Startup.cs):
// to allow access to apple-app-site-association file
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, #".well-known")),
RequestPath = new PathString("/.well-known"),
DefaultContentType = "application/json",
ServeUnknownFileTypes = true,
});
Tested in AWS Serverless Application (.NET Core 3.1)
I want to get access to multiple folder locations from my web api to display image.
I can't change the folder locations (depending on devices on which I don't have right to modify anything).
for one of the folders I did:
string FolderToListen = Configuration["xxx:yyy"];
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(FolderToListen),
});
and now I would like to do:
string FolderToListen2= Configuration["xxx2:yyy2"];
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(FolderToListen),
FileProvider = new PhysicalFileProvider(FolderToListen2),
});
but it doesn't work.
Is there any way to pass multiple folders to UseStaticFiles ?
You can register UseStaticFolder twice:
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(FolderToListen),
});
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(FolderToListen2),
});
This answer is wonderful, localhost'ly, but when I push an .NET Core 3.1 app into Azure Web Apps it completely goes 500 on me.
Looking around the web it appears that duplicate entries are not allowed ... although this seems more like in Startup services.
I think I too would prefer a solution like,
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(FolderToListen),
FileProvider = new PhysicalFileProvider(FolderToListen2),
});
not that its possible, of course, but the duplicate entries simply don't seem to work.
I have this in a Startup.cs file for a small project for a webserver hosting static files with Kestrel:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var configBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json");
var config = configBuilder.Build();
var options = new RewriteOptions()
.AddRedirectToHttps();
app.UseRewriter(options);
DefaultFilesOptions defoptions = new DefaultFilesOptions();
defoptions.DefaultFileNames.Clear();
defoptions.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(defoptions);
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), #"static")),
RequestPath = new PathString("")
});
loggerFactory.AddConsole(config.GetSection(key: "Logging"));
}
}
However, it doesn't try to load an index.html or anything. If I access it manually, it does indeed work.
Any ideas?
Thanks
Ideally your index.html should be under the web root path (wwwroot), however, if your file is under ContentRootPath\static (as it appears to be), you will need to change your code to specify the DefaultFilesOptions.FileProvider as follows:
PhysicalFileProvider fileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), #"static"));
DefaultFilesOptions defoptions = new DefaultFilesOptions();
defoptions.DefaultFileNames.Clear();
defoptions.FileProvider = fileProvider;
defoptions.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(defoptions);
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = fileProvider,
RequestPath = new PathString("")
});
Note: you are probably better off using IHostingEnvironment.ContentRootPath (env.ContentRootPath) rather than Directory.GetCurrentDirectory() on the first line (just in case you want to change the content root in your WebHostBuilder at some point).
Kudos to CalC for his insight, which got me closer to the answer for asp.net core 2.2. Here's what I ended up needing to do to serve a default document outside of the main web server root in Azure:
public void Configure(IApplicationBuilder app){...
// content is physically stored at /site/abc on an Azure Web App, not /site/wwwroot/abc
string path = Path.Combine(Directory.GetCurrentDirectory(), "abc");
PhysicalFileProvider fileProvider = new PhysicalFileProvider(path);
DefaultFilesOptions options = new DefaultFilesOptions
{
FileProvider = fileProvider,
RequestPath = "/ABC",
};
options.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(options);
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = fileProvider,
RequestPath = "/ABC"
});
}
The key was using matching RequestPath and FileProvider values
I currently have a generated index.html, js and other static files living in a folder and I'm marking that folder as a static folder (by adding the following in the Configure method in Startup.cs:
app.UseDefaultFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new Path.Combine(env.ContentRootPath, #"../build")),
RequestPath = new PathString("/app/")
});
Is there a way to set index.html as the default response for this */app route? Because right now localhost:5000/app/ returns a 404 while localhost:5000/app/index.html returns the index.html.
EDIT: I missed to mention that I did try using app.UseDefaultFiles() like mentioned in docs but it does not work for me. The server still returns a 404
One of the comments in that docs has clarified it:
Kieren_Johnstone
Featured May 22, 2017
The section, "Serving a default document" misses some vital
information. If you configure your UseStaticFiles to work off a
non-root RequestPath, you need to pass the same FileProvider and
RequestPath into both UseDefaultFiles and UseStaticFiles, it seems.
You can't always just call it as stated in the section.
So that means, you should write something like this to enable your specified folder to provide a default page:
app.UseDefaultFiles(new DefaultFilesOptions()
{
FileProvider = Path.Combine(env.ContentRootPath, #"../build")),
RequestPath = new PathString("/app/")
});
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = Path.Combine(env.ContentRootPath, #"../build")),
RequestPath = new PathString("/app/")
});
Use this:
public void Configure(IApplicationBuilder app)
{
// Serve my app-specific default file, if present.
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
}
For more details follow this link:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files
and go to section: "Serving a default document"
from documentation:
Setting a default home page gives site visitors a place to start when
visiting your site. In order for your Web app to serve a default page
without the user having to fully qualify the URI, call the
UseDefaultFiles extension method from Startup.Configure as follows.
public void Configure(IApplicationBuilder app)
{
app.UseDefaultFiles();
app.UseStaticFiles(); // For the wwwroot folder
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), #"build")),
RequestPath = new PathString("/app")
});
}
UseDefaultFiles must be called before UseStaticFiles to serve the
default file.