I know similar questions have been asked before, but the only answers are six years old, and the projects people refer to seem like they're not being maintained.
I want to use Razor in a console app or a class library to render HTML. I would also like to have working Intellisense in the .cshtml files.
Currently, I am able to jury-rig this by doing the following:
Custom Tool
property to RazorTemplatePreprocessor
This causes Razor syntax to be recognized. So if you have Test.cshtml
, it generates a class called Test
that you can use like so:
var test = new Test();
test.Model = "Hi there";
var html = test.GenerateString();
Console.WriteLine(html);
This is just about good enough for my purposes. However, the actual coding experience within the .cshtml file is pretty broken:
var
because it's C# 2.@model
keyword is not recognized.Weirdly, if you just ignore all of these errors, the HTML is actually generated correctly, including use of the libraries and @model keyword that the Razor engine complained about. However, this causes major mental clutter because if you have any number of .cshtml files, you very quickly get into hundreds and thousands of these errors mixed in with real errors.
Is there anything I can do to cause the actual Razor coding experience to work more like it does in an ASP.NET web app?
A console application, in the context of C#, is an application that takes input and displays output at a command line console with access to three basic data streams: standard input, standard output and standard error.
cshtml files are razorpages or MVC views, they does not contain any C#-written client-side code. If you wan to do so, you must use JavaScript. However, a . razor file, also know as a Razor component, can have C# written in it and run on client's browser.
I have been working on this sporadically since I asked the question nearly two years ago, and I believe I have a 99% non-clunky solution. Everything below works for me in Visual Studio 16.4.5.
Here's what I have learned about getting Razor to work in console and library projects.
@model
and the @using
keywords work correctly, Intellisense works correctly, lambda expressions work correctly, everything seems to work properly.Here's what you have to do:
To add a Razor file:
Add a new HTML file, but name the file with a .cshtml
extension.
Select the file in Solution Explorer. In the Properties window, under Custom Tool, enter RazorTemplatePreprocessor
. A .cs
file will immediately be generated.
To consume the generated class:
var razor = new MyRazorClass();
razor.Model = "Hello from Razor"; // Assumes @model string in the Razor file; custom classes are fine too.
var html = razor.GenerateString();
Console.WriteLine(html);
To resolve the errors in the Error List (which incidentally do not seem to affect functionality but certainly create mental clutter):
Add NuGet references to:
Microsoft.AspNetCore.Mvc.Core
Microsoft.AspNetCore.Mvc.Razor
If you are adding your Razor files to a .NET Standard library, you'll get a bunch of the following errors:
Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
To fix this, add the following two lines to the project file:
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable> <!-- Add this line -->
<LangVersion>8.0</LangVersion> <!-- Add this line -->
</PropertyGroup>
At this point, the project should compile with no errors or warnings!
However, it doesn't work perfectly. There some oddities, which give me some concern that things might unexpectedly break on me in the future.
These problems only seem to occur when using Razor files from .NET Standard libraries:
.cshtml
file in two different ways:a. In what I believe is the correct way, the .cshtml
file has as its only descendant a generated .cs
file. That file in turn has two generated classes, YourRazorClass
and YourRazorClassBase
. Each of those can be expanded to show the class members, which have nice, human-readable names.
b. Sometimes, however, an underscore-prefixed class appears as a direct descendant of the .cshtml
file (e.g., _MyTestRazorClass
), Also, its class members are different.
This seems to appear and disappear from the Solution Explorer and I don't think it causes any harm, but it certainly causes some mental clutter as you wonder what on earth is going on.
[Project Name]
> Dependencies
> Analyzers
, there are a bunch of warnings that get propagated up into the same section of any project that consumes the library. This also creates mental clutter. Fortunately, you can turn these off by doing the following:a. Right-click the project and choose Properties
.
b. Under Code Analysis
, uncheck the Run on Build
and Run on Live Analysis
boxes.
One final note: I have not yet tested using a .NET Standard library set up in this way inside a Xamarin project yet (this is the scenario that originally had me going down this road), but I will do so in the future and update this answer at that time.
UPDATE: I have now used this technique in a released Xamarin app! The only weirdness is that you can't copy-paste .cshtml files to create a new one. It screws up both the original file and the copy and you have to go edit the project file to fix things. Instead, just manually add a new file as described above each time.
I hope this helps someone. And if anyone figures out what is going on with the weirdness in Solution Explorer, I would love to know!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With