How to deploy cshtml files in asp.net core - asp.net-core

How to deploy cshtml files in asp.net core?
If I publish my asp.net core project the cshtml doesn't get published.
How to run the cshtml file directly in Chrome?
Here's some code to explain this further
My Program.cs file contains
public static void Main(string[] args)
{
//since zoho can pass only 10 parameters in one webhook we are splitting into two updates
//update1
UpdateClassBoatFromZohoModel upd = new UpdateClassBoatFromZohoModel();
upd.OnGet();
//update2
UpdateClassBoatFromZohoModel2 upd2 = new UpdateClassBoatFromZohoModel2();
upd2.OnGet();
//CreateWebHostBuilder(args).Build().Run();
}
Now each of these files UpdateClassBoatFromZoho.cshtml and UpdateClassBoatFromZoho2.cshtml are to be served in the browser with different querystring parameters. How to do that?

You can't because that's not how any of this works. The cshtml files cannot be run on their own. They are not served, for one, and they contain pre-processed code that only works in conjunction with the rest of the ASP.NET Core request pipeline. Even if you could access them directly, they wouldn't be anything but a text file (i.e. a web browser would have no idea what to do with it).

Precompilation of pages/views is the default behaviour. It is possible to skip this step and to publish the raw .cshtml files, resulting in pages/views that are updateable in a similar way to classic ASP or the ASP.NET Web Pages frameworks. In other words, you can make changes to the .cshtml files and then copy them to the web server while the application is running, and the new content will take effect immediately.
If you would like to adopt this approach, add an MvcCompileOnPublish node to your .csproj file, with the value set to false:
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
</PropertyGroup>
This will result in a Pages folder containing the content pages and a refs folder containing the libraries required for the application:

Related

What is the ASP.NET Core convention for static, non-MVC pages?

I'm converting my website from Web Forms to .NET Core. I don't want to change the directory level of various files, e.g.:
MYDOMAIN.com/FAQ.html
MYDOMAIN.com/Privacy.html
By using the UseStaticFiles() middleware, I can place these in the wwwroot folder and they will be served as is. However, I don't know how to apply a Layout page with my website theme to those files since they're outside of the MVC framework.
I'd like to leverage the Layout files and MVC framework by using .cshtml files, but I'm also trying to avoid the extra controller directory that's imposed on the URL:
MYDOMAIN.com/home/FAQ.html
MYDOMAIN.com/home/Privacy.html
Maybe this is short-sighted, but how do developers handle this?
And actually, my existing files are .aspx at the moment, not .html files so that adds another level of confusion as to what the convention is for migrating to .Net Core. Should I use any .aspx files anywhere in the project or should they all be converted to .cshtml / .html files? Or something else?
I have successfully implemented a solution, but it's kind of a hack. I add controllers for each static page, for example I created both a FAQController.cs and PrivacyController.cs.
Each controller has only Index() actions so that they can take advantage of _Layout.cshtml and _ViewStart.cshtml.
It seems like a roundabout way to go just to move the following up one level e.g.
MYDOMAIN.com/FAQ
MYDOMAIN.com/Privacy
but it works.

Is there a way to serve a Blazor app from a specific controller action in a MVC app?

I'd like to set up a controller action in a already existing ASP.NET Core 3.0 MVC project to serve a Blazor app. I've seen something similar with other SPA frameworks in the past, the View for the action just includes contains the script tag with the bundle, there's usually some other setup like having the SPA build placed on wwwroot for the MVC project.
Looking at the Blazor app it seems similar to some extent, where the index.html file includes the wasm script. But I'm honestly not sure where to start to set it up. Any ideas?
Seems you're using Blazor Client Side. Basically, the entry for Blazor Client Side App is the <script> that loads the blazor.webassembly.js. And this script will download all the static assets( *.wasm and *.dlls) dynamically. Note that if you can make these assets available, you can host the Blazor Client Side App even without ASP.NET Core.
Since you're using ASP.NET Core MVC as the server, an easy approach would be :
Add a package reference to Microsoft.AspNetCore.Blazor.Server so that we can serve the *.wasm *.dll files with just one code.
<PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="3.0.0-preview9.19465.2" />
Add a project reference to your ClientSide Project so that we can generate the statics from source code. Let's say your client side web assembly app is MyClientSideBlazorApp:
<ProjectReference Include="..\MyClientSideBlazorApp\MyClientSideBlazorApp.csproj" />
And now you can register a middleware within the Startup.cs to serve the static files:
app.UseClientSideBlazorFiles<MyClientSideBlazorApp.Startup>();
app.UseStaticFiles();
Finally, within any page/view that you want to serve the blazor, for example, the Home/Privacy.cshtml view file, add a <script> to load the entry and also a <base> element to make sure the relative path is correct.
#{
Layout = null;
}
<base href="/">
...
<app>Loading...</app>
<script src="/_framework/blazor.webassembly.js"></script>
It should work fine now.

Let's Encrypt with ASP.Net Core and Azure App Service

I have a Runbook in Azure that uses AcmeSharp to generate Let's Encrypt certificates for a website running in Azure App Services. I have used it many times successfully on many ASP.Net sites. Apparently I've never tried it on an ASP.Net Core (2.2) site until now.
I'm pretty sure I was running into the problem described in this blog post - https://ronaldwildenberg.com/letsencrypt-for-asp-net-core-on-azure. Basically, the script publishes a static file to /.wellknown/acme-challenge/randomstring/index.html in my site and then Let's Encrypt tries to verify that file. I'm getting a 404 when trying to hit this URL even though I can see it in the file system in Kudu.
I felt like this was a static file issue in ASP.Net Core and when I found the blog post referred to above - I thought that was going to be the answer. I changed my code as prescribed in the article, but I'm still getting the 404.
Slightly different than the article, instead of files with long random strings of characters like in the article screenshot, my script generates a string like that but creates a folder with that name. Inside each folder is one file (named index.html) that contains the validation info Let's Encrypt is looking for. You can see this at http://www.technicality.online/.well-known/acme-challenge/
You can see the folders are browsable and if you click one, you can see the link to index.html. The problem is - if you click index.html, you get a 404. I've put this in my Startup.Configure:
var rootPath = Path.GetFullPath(".");
var acmeChallengePath =
Path.Combine(rootPath, #".well-known\acme-challenge");
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(acmeChallengePath),
RequestPath = new PathString("/.well-known/acme-challenge"),
});
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true
});
(I don't think I need the ServeUnknownFileTypes since my file is index.html, as opposed to the long random string in the blog post, but I don't think this should hurt anything either.)
I thought maybe the issue was that the file didn't contain valid html (just a string of characters), but I put another file that did contain valid html and I get a 404 when clicking that one as well.
Is there some other ASP.Net Core (or Azure App Service) detail I'm missing to make the application serve up the index.html files?
I figured this out and am posting the answer to hopefully keep someone else from making the same mistake I did. The issue wasn't at all what I thought it was, but rather - there are two "wwwroot" folders in an ASP.Net Core Azure App Service hosting environment and I wasn't paying close enough attention.
The file system path where Azure hosts your application is D:\home\site\wwwroot. In a "classic" ASP.Net scenario, your static files go in that folder. In an ASP.Net Core scenario, another wwwroot folder is created underneath that one. My script (written for ASP.Net) was creating the ".well-known\acme-challenge" folder beneath the first one. The standard app.UseStaticFiles() doesn't help with those.
Basically, I had:
-home
--site
---wwwroot (hosting root)
----wwwroot (ASP.Net core static files folder)
----.well-known (this was a sibling of the 2nd wwwroot and needed to be a child)
I needed to change my script to put my static files under the 2nd wwwroot so that the app.UseStaticFiles() would serve those files.

How is configuration data protected in ASP .NET 5?

Rather than requiring Web.config, ASP .NET 5 provides a number of options to provide configuration data. Info on this can be found at:
Introducing ASP .NET 5 by Scott Guthrie
How can we store configuration data in new asp.net vnext? (StackOverflow)
ASP.NET vNext Moving Parts: IConfiguration by Louis DeJardin
There's an interesting question in the comments section of ScottGu's article:
The config.json file in the example, how is that protected by the webserver/http server? web.config is protected by IIS, but if any file can be used (which is great), it also comes with the burden that the webserver shouldn't serve the file out if one requests it in a URL. Or are there prefab names to choose from?
Can anyone answer this?
In previous versions of ASP.NET root of the project was also a root for the website. Some mechanisms were created to prevent access to files which should not be accessible to the outside world (like a whitelist of mime types, RequestFilteringModule).
This changed in ASP.NET 5 as a website root is no longer a project root.
Website root folder is a subfolder in your project directory (named wwwroot by default, but can be changed in project.json).
This means that everything outside a website root folder is not accessible to the outside world.
config.json file is outside of wwwroot so it won't be ever handled by any requests.

VirtualPathProvider on IIS 6 does not handle file stream caching correctly

I am working on a framework where .aspx and .master pages are embedded in an assembly, using VirtualPathProvider to route a url to a specific embedded resource.
Sample url: /_framework.aspx/mypage.aspx (which uses /_framework.aspx/mymaster.master)
_framework.aspx will make IIS6 route the request through ASP.NET framework
everything after the .aspx is treated as a PathInfo in the .NET framework
In Visual Studio 2008 web server, the virtualPath is correctly: /_framework.aspx/mypage.aspx
but in IIS6 the virtualPath is: /_framework.aspx
If I request two files: /_framework.aspx/file1.css and /_framework.aspx/file2.css
the file2 will have the same content as file1.
I suspect that IIS6 considers the file path (_framework.aspx) and caches the file stream which is returned from the assembly, thus treating both urls as the same file.
Temporary solution:
I've implemented a CacheDependency class like this
class ImmediateExpiryCacheDependency : System.Web.Caching.CacheDependency
{
public ImmediateExpiryCacheDependency()
{
base.NotifyDependencyChanged(null, null);
}
}
It now expires the file stream cache, but doens't work with master pages, I guess because it is requested before the cache is expired through NotifyDependencyChanged.
Needed solution:
If I returned null in GetCacheDependency, IIS6 doesn't expire the file immediately. What is the correct way to immediately expire a file or disable the caching entirely. Even better, I would like to correct the way that IIS6 deals with the url, since the caching is actually good, if it would use the full file url.
Through my work in the ASP.NET Development Web Server, I had come to conclude that the correct FilePath would include the PathInfo, but I understand now that the IIS implementation is correct.
I changed my code so that ASP.NET files (aspx, ashx) would have a path such as /_framework/Default.aspx (since these files will be routed without special configuration) with a master page path such as /_framework/Site.master (since this is routed internally in the ASP.NET engine) and with image resources with a path /_framework.ashx/image.gif (since the .ashx will be routed to the ASP.NET engine, from where I will then use a kind of StaticFileHandler).
This way, all pages and resources can reside and remain entirely in the assembly :-)