hostfile.json webroot property not serving static files - asp.net-core

Going nuts :-)
I've installed the latest ASP.NET Core (RC2).
I'd like to be able to create a *.sln, with multiple *.csproj: one for server side development, and one for just client side development.
The reason we are keeping them separate is so that we can have the option of giving the the clientside *.csproj to external developers with better UI skills to work on without needing to know much about the server side code. They could work on the client side html/js using Visual Studio Code or other light weight IDE, and not requiring Visual Studio to get involved.
In the client *.csproj, I'd like to serve static files (html/js/css) for an angular project from the root directory, not from the wwwroot directory, so that gulpfile.js relative paths, etc are identical to how one would set up an angular project without Visual Studio.
As I understand it, the rules are now:
* use the webroot setting in hosting.json if hosting.json file exists.
* otherwise, use wwwroot.
* if that's missing, use root.
* See: https://github.com/aspnet/Hosting/issues/450
First, checked that I had set up static page routing. Created a wwwroot/index.html page. Tada! Works.
Now, renamed the directory to app/ and updated hosting.json to point to it. After a reload of the project, the app/ folder changed icon..good...run...no joy. Fight with it for a while. No success...
Then delete the app/ folder and hosting.json file altogether. End up definitely wanting to throw something...
The only way I'm getting static files is if the folder is called wwwroot. Whether I have a hosting.json file or not.
That's contrary to the documentation at: https://github.com/aspnet/Hosting/issues/450
Has anybody else succeeded in getting rid of the wwwroot folder? If so...how?!?!?
Thank you!

Although you can open up the root of your ASP.NET Core app for serving static files, it's not a good idea because once you do, there's nothing preventing someone from navigating to project.json or any other file in the root.
That being said, here's how you would go about serving up static files outside of wwwroot.
First, create a static class that returns IApplicationBuilder. In here you will define what physical path to make accessible along with an optional URL re-write of that path (see comments in the code):
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.Extensions.FileProviders;
public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder UseRootResources(this IApplicationBuilder app, HostingEnvironment env)
{
//var path = Path.Combine(env.ContentRootPath); // WARNING - this opens up the root of the app
var path = Path.Combine(env.ContentRootPath, "static"); // this would allow for serving up contents in a physical path folder named 'static'
var provider = new PhysicalFileProvider(path);
var options = new StaticFileOptions();
// the below line re-writes the path name of the physical path, it can have the string value of anything you want to call it
options.RequestPath = ""; // in this example, an empty string will give the *appearance* of it being served up from the root
//options.RequestPath = "/static"; // this will use the URL path named static, but could be any made-up name you want
options.FileProvider = provider;
app.UseStaticFiles(options);
return app;
}
}
Next, in the Startup.cs, call that function from the Configure method:
app.UseRootResources((HostingEnvironment)env);
Now you can serve up static files outside of wwwroot! Referencing the static file in HTML will use the path you defined in the Options.RequestPath as set in the ApplicationBuilderExtensions class. Assuming you left the RequestPath to an empty string to simulate the root, you then call the resource like it lived there (even though it really lives in the 'static' folder) thanks to the magic of URL re-writing:
<img src="bus.jpg"/>

Related

Hosting ASP.NET Core application in Windows Service with Single Executable gives wrong working directory path always

I have hosted ASP.Net core 3.1 application in Windows Service. It works fine and I am able to navigate to pages.
Now i am trying to change deployment as single executable file from "Produce single file" option in Publish settings. after this I started getting errors 404 for static files under wwwroot folder. below are the folders and actucal values:
Directory.GetCurrentDirectory() = C:\WINDOWS\system32 - This is Correct as per documentation.
AppDomain.CurrentDomain.BaseDirectory = C:\WINDOWS\TEMP\.net\app_windows_servicename\yjzzq0br.phx\
// This should have been the installed application location.
hostingContext.HostingEnvironment.ContentRootPath= C:\WINDOWS\TEMP\.net\app_windows_servicename\yjzzq0br.phx\
// This should have been the installed application location.
This path contains extracted binaries but does not contain folder and content for wwwroot.
If i manually copy wwwroot folder and content to this temp location then hosted asp.net core service under windows service serves the static files properly.
help me on this. Same behavior was observed in ASP.Net Core 3.0.1 also.
I don't know the exact reason why this happens, it seems like an intentional design decision though, but more information can be found here.
The linked post includes a workaround that I can confirm does resolve the problem. I will sum up the solution here:
In program.cs there is a method called CreateHostBuilder. By default, you will probably have something like this...
public static IHostBuilder CreateHostBuilder(string[] args)
{
var builder = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
builder.UseWindowsService();
return builder;
}
To resolve the issue, you need to override the default content root and specific the same directory of the application EXE file. The can be done like so:
var pathToExecutable = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
builder.UseContentRoot(pathToExecutable);
Note. It is worth noting that this doesn't seem to work when running in debug mode directly from Visual Studio, so it might be worth wrapping it in a condition. One simple option is to just check for the existence of an attached debugger like so:
if (!System.Diagnostics.Debugger.IsAttached)
{
var pathToExecutable = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
builder.UseContentRoot(pathToExecutable);
}
Warning. There is some degree of assumption here that not having a debugger attached means it's running as a service. You should decide for yourself what condition works best for your needs. You could opt to use preprocessor directives to detect "release mode", for example.
Works but only if UseContentRoot is applied to the IHostBuilder and not within ConfigureWebHostDefaults. Eg: Host.CreateDefaultBuilder(args).UseSerilog().ConfigureWebHostDefaults(...).UseWindowsService().UseContentRoot(...)

What are ASP.NET Core Static Web Assets?

There is a lot of hidden magic that occurs in HostBuilder.ConfigureWebHostDefaults() (that eventually calls ConfigureWebDefaults). I would like to understand it better as there is no documentation that I can find about it.
This code seems to be loading some static files. What are static web assets and why do we need them? Is this something to do with embedding static assets into libraries for Blazor?
builder.ConfigureAppConfiguration((ctx, cb) =>
{
if (ctx.HostingEnvironment.IsDevelopment())
{
StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);
}
});
Static Web Assets are static files made available from a Razor Class Library (RCL):
An RCL may require companion static assets that can be referenced by the consuming app of the RCL. ASP.NET Core allows creating RCLs that include static assets that are available to a consuming app.
UseStaticWebAssets inserts additional file providers (instances of StaticWebAssetsFileProvider), using a manifest file ({environment.ApplicationName}.StaticWebAssets.xml if not set via IConfiguration) to determine a list of mappings from path to base path.
As an example, when using the ASP.NET Core Identity UI RCL, the manifest file for your app looks something like this:
<StaticWebAssets Version="1.0">
<ContentRoot BasePath="/Identity" Path="\path\to\.nuget\packages\microsoft.aspnetcore.identity.ui\3.0.0\staticwebassets\V4" />
</StaticWebAssets>
This all ends up with a CompositeFileProvider being set for the IWebHostEnvironment.WebRootFileProvider. This composite provider does two things:
Processes the wwwroot/ static files as usual (assuming default configuration).
Delegates any files requested from wwwroot/Identity to the extracted NuGet package content folder for the Identity UI.
As the code snippet from your question shows, this only happens when running in the Development environment. When your app is published, the files in question get copied up into the wwwroot folder, as though they were part of your app.

Purpose of a virtual path prefix in Express

The way to serve static on the server side seems pretty straightforward in Express:
To serve static files such as images, CSS files, and JavaScript files,
use the express.static built-in middleware function in Express.
Pass the name of the directory that contains the static assets to the
express.static middleware function to start serving the files
directly. For example, use the following code to serve images, CSS
files, and JavaScript files in a directory named public:
app.use(express.static('public'))
Now, you can load the files that are in the public directory:
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
Express looks up the files relative to the static directory, so the
name of the static directory is not part of the URL.
To use multiple static assets directories, call the express.static
middleware function multiple times:
app.use(express.static('public'))
app.use(express.static('files'))
Express looks up the files in the order in which you set the static directories with the express.static middleware function.
I get the idea of a virtual path prefix, but why would you use it?
To create a virtual path prefix (where the path does not actually
exist in the file system) for files that are served by the
express.static function, specify a mount path for the static
directory, as shown below:
app.use('/static', express.static('public'))
Now, you can load the files that are in the public directory from the /static path prefix.
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
I know it's a little late, but hope this could help you. BTW, I take no credit for the answer, just went to dive a little deeper on your concern and found this.
This technique comes in handy when providing multiple directories to serve static files. The prefixes are used to help distinguish between the multiple directories.
If you would like to dig deeper. I found it on this link:
https://guide.freecodecamp.org/nodejs/express/

How to change path in the laravel config if It's located in the folder upper then public?

I have laravel 5 and config file in the config folder and My css located in the resources folder which is a same level with public folder where located index.php. Virtual Host Apache config looks to the public folder as a root site directory, but in this situation I cannot declare correct path from /public/index.php to the resources folder.
From one side I can try easy way and just relocate public folder into root of the laravel, but I don't like this way, any ideas?
Use resource_path('path/to/your/css')
https://laravel.com/docs/5.3/helpers#method-resource-path
EDIT
The most logical is to include your stylesheets in your public folder though. If you need to style a page, the style is public anyway. So why not put in the public folder. There's 2 options to do this:
Do it manually by just copying/moving the files
Use an automated tool like Gulp or Laravel's own Elixir, which provides a really easy way to copy your assets.
add this code in public/index.php
$app->bind('path.public', function() {
return __DIR__;
});

Yii framework proposed folder structure not working

I'm relatively new to Yii. I've managed to get a sample application up and running but as I am now moving to a real project, I would like to use the following folder structure for increased security:
[Server root (/) ]
- yii
-- framework
-- requirements
[Server htdocs]
- myapp
-- public
--- assets
--- css
--- images
--- themes
--- index.php
-- private
--- protected
All is fine when I leave the protected folder inside the public folder but I don't want to do this.
The only way I can get it to work using my proposed structure is if I create a symlink inside the public folder pointing to the protected folder inside the private folder. If I reference it directly in the private folder it just gives me a blank page upon app load.
I've double checked my configuration paths and permissions.
Any help is appreciated.
You can configure Yii to use the folders you want for your specific needs, eg. protected-folder, assets, themes, etc.
Have a look at "The directory structure of the Yii project site" for an example.
You can put your protected folder where you want, but you have to tell it to index.php. In your case, the line where it says:
$config=dirname(__FILE__).'/protected/config/main.php';
must say:
$config=dirname(__FILE__).'/../private/protected/config/main.php';
And same in index-test.php
There is an open source project called Yii Boilerplate which proposes application structure for Yii to use in large projects that require scalability.