.net core 2.1 reusing _Layout throughout various projects - c#

I am trying to reuse the same _Layout.cshtml file, throughout multiple .net core 2.1 Razor Page projects. Currently I have a Razor Page Class Library (Common shared project) that is where the _Layout.cshtml file will be located. Along with the layout file there are css and js files that should also be accessible to all other projects (I was able to make this work).
secondary projects will have references to the Common shared project and should be able to utilize the _Layout.cshtml file from it.
My issue is that currently it is not loading the common _layout file when I am accessing pages from these projects, instead it loads its own layout file. If I try deleting this file it throws the error that it cannot find the layout file. However, if I load a page contained inside of the Common shared project it does load its own _layout.
I have used the following tutorials to get where I am at but I could not figure out how to make the secondary projects load the layout in the Common shared project.
Including Static Resources In Razor Class Libraries In ASP.NET Core
Can Razor Class Library pack static files (js, css etc) too
Reuse UI With Razor Class Libraries (RCL) In ASP.NET Core
Please keep in mind that 2 of these articles are based on sharing the css and js files (which did work) but I have read up on other examples for the layout as well and have had no luck (currently I don't have the links to those other articles)
As far as what I have coded I'm currently experimenting on a sample project and its the same as the first article (Including Static Resources In Razor Class Libraries In ASP.NET Core).
UPDATE
Utilizing the 3rd link (Reuse UI With Razor Class Libraries (RCL) In ASP.NET Core) I was able to accomplish my goal. However, I was using this same strategy previously and it was not working. I am going to try playing around with this a bit more. If I have any other updates I will post them.

So apparently since I was working off of the Including Static Resources In Razor Class Libraries In ASP.NET Core link the example left the default razor page class library structure containing the Area/MyFeatures folders. I modified this to work like the last link Reuse UI With Razor Class Libraries (RCL) In ASP.NET Core where the Common shared project is structured the same way that the web application project is (no Area or MyFeatures folder). I also added:
#addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers
to the end of my _ViewStart.cshtml located in the Common shared project.
Also just as a note you must delete the _layout.cshtml and _viewstart.cshtml from the web application otherwise it will override the shared project layout.
Anyhow this seems to have fixed the issue and it is now working.

Related

Using #html.React() in a .cshtml razor view for a component that's inside an npm package

I have a .NET Core 3.1 ASP.Net project using razor views.
I'm using React components in those razor views by adding app.UseReact() to my startup.cs and then calling #html.React("myComponent") inside the .cshtml files. I'm not using React as an SPA.
This works fine when I have "myComponent" inside a .tsx file that's in the web project.
My company want to move some of these react components into npm packages so that they can be re-usable across projects. After moving the .tsx file for "myComponent" to an npm package, and referencing the package in package.json, upon running the project I get the error "myComponent" is not defined.
I've run a npm install and I can see that the package and the .tsx file for "myComponent" are in the node_modules folder of the project, but I'm guessing that asp.net mvc doesn't know to look in there for components when I'm calling #html.React("myComponent") inside the .cshtml file.
What do I need to do to make asp.net find the component? Do I need to explicitly import it somehow?
For now, I've managed to get by with a dirty hack. I'm using a pre-build script to copy the component's tsx file out of the node_modules folder and into the ClientApp folder, so that it sits along with the projects other react components. But it's not ideal because another developer may not realise that it's being copied there and try to edit it if they want to make changes, when really they should be editing the file in the npm package.
Direct Answer
Adding an npm package does not make it available to MVC automatically so you'll have to do some sort of file copy at some point in your development cycle. This can be a npm postinstall script or even something more complex such as a Grunt/Gulp task. You can even trigger the tasks via npm scripts if you choose to do so. All and all there's no "right" or "standard" way of doing react with MVC so you're free to make your own choices, carefully :)
if they want to make changes, when really they should be editing the file in the npm package.
Yes they will need to know about the npm package, clone its source git, update it, publish it, then update their project to the latest package version.
My Experience (read pain)
How can I forget this pain. It was a mistake to have React as a non-SPA because you're essentially making every main view an independent SPA and this has some major drawbacks. Firstly how do you share data between razor view and the component on the same page? The way we did it was to JSON stringify the data into a variable and then load this variable in the component (you can also opt-in for an additional http call to a web api endpoint). You can already see the start of fire as the pages evolve over time. Next problem we came across was bundling optimizations. We had to write a bunch of code in order to bundle per page and save outputs to the wwwroot folder. Developers coming on board often confused as to what this does in main razor views (e.g. Views/Home/Index.cshtml):
<script src="/Home.Index.min.js"></script>
Wait where is the /Home.Index.min.js file? This is created by the bundling task for this page at build time and copied to the scripts folder. Next question a developer would ask was why the page is missing its "user interface", of course they've forgotten to add an additional task for the new razor page they created (well and the script entry)... I can write for days on how terrible the idea of one bundle per razor page was and how messy the code became a few years into the maintenance cycle, not to mention the mysterious comeback of JQuery!!. The truth is that JS needs to be tree-shaken, minified and optimized. ASP.NET has no such a thing, the nuget packages simply glue your JS files and provide some level of minification, none of which can match standard bundlers such as webpack or parcel. This was another reason to have our bundling tasks run a bundler for each page. This also took care of the npm dependencies and third-party libraries.
My Recommendation (opinionated)
Save yourself and simply keep them separate. There's no such a thing as a razor page with react, that's a made up hack to make razor compatible with the evolved web technologies. Some of this applies to php so it's not just a Microsoft thing.
Best you can do is to create a SPA and use web api for back-end. You can have razor but they will be independent pages, for example the login page can be a razor page which then takes you to the home page that's a SPA written and bundled via react and the surrounding ecosystem. Interactions in the SPA happen over REST or even GraphQL apis.

Have you ever seen Razor used without MVC in a JavaScript SPA?

I recently took over an application which combines a number of cshtml files written in Razor with a JavaScript spa. I've never seen this structure before and am wondering if anyone has run into this before?
/api
/App_Code
MyCache.cs - caches some data from an external API
Application.cs - looks like the code behind for Global.asax
Api.cshmtl - Uses razor syntax but the entire file is C# and it gets an auth Token and adds it to all api calls.
Global.asax - without global.asax.cs
web.config - not much helpful in here.
index.cshtml
Most of the .cshtml files use Razor syntax. Some are just calling a method from the MyCache.cs via #Html.Raw(myMethodFromCache).
Unfortunately, I don't have a .csproj or .sln file, so it's really hard to guess how this gets compiled. Also no package.config, so I don't know what version of the assemblies, but it only includes:
System.Web.Helpers
System.Web
System.Web.WebPages.Deployment
System.Web.WebPages
System.WebPage.Razor
Have any of you see something like this before? Do you know if this is some older way of handling Spas with .NET?
Any suggestions you have are appreciate.
I finally figured out what this is. It is using ASP.NET Web Pages which is a package available on NuGet. It is a trimmed down version of ASP.NET with the Razor syntax and .cshtml pages without all of the overhead of MVC.
And it was set up to run as a "web site" instead of "web application" which means the application is built at runtime.

Serve static files in blazor hosted project

It is a pretty simple Task, I want to use images in my razor pages which are located in wwwroot/css/images and use it in html like this.
<img src="~/css/images/logo.png"/>
In a normal ASP.Net Core application I would just add app.UseStaticFiles() in the Configure method, but since this is a blazor hosted application, it changes nothing.
I also tried adding the app.UseStaticFiles() in the server project, but with no success either.
If you want to try it out yourself just create a blazor-hosted project from the templates and try to serve/display images like I did.
Blazor serves static file just fine. The issue you’re having is the syntax you’re using to reference the file. You just need to drop the ~ symbol.
<img src="/css/images/logo.png" />
One precision about that...the static file root for anything
in blazor starts at the wwwroot folder. wwwroot is
simply taken for granted and is omitted in the actual
path you need to use to ask for a static file. using :
"/css/images/logo.png"
could also be expressed :
"css/images/logo.png"..I'm pretty sure.
If you are in a Razor Class Libray...there is also a wwwroot for
the Razor Class Library itself. When used is a Blazor
Wasm Client the filepath for any static file in the RCL becomes :
"_content/[RCL assembly name]/css/images/logo.png"
Note that even for classes and stuff you implement inside the Razor Class Library itself,
even you are in that library defining stuff...static files
in your own wwwroot inside a Razor Class Library are called using
the "_content/[RCL assembly name]" prefix.

Razor Class Library - Is there a way to compile all Pages/ as Pages/<module name>?

How can you automatically move all RCL pages to a sub-folder of Pages/, such as Pages/<module name> at compile-time, or at WebApplication import-time?
I need this to be transparent such that, in the RCL solution, all pages are in Pages/, but compiled, they are in Pages/<module name>. Or, they're compiled at Pages/, but when imported by the WebApplication, they are hosted in Pages/<module name>.
Is there a project level setting which can prepend the compiled pages with some folder name? Or some other mechanism I can use to achieve the same effect?
Attempted Solutions
I thought about adding routing options to the RCL pages themselves via the #page razor directive but decided against it because it would have to be done to each page individually, and I need something more general which will apply to all pages in a RCL.
I looked up ways to import the RCL content under a different folder via Startup.cs's ConfigureServices() and Configure() but to no success with Conventions. Both PageRouteModel and PageApplicationModel conventions only see the overwritten pages. Also tried to use ConfigureFilter but it ran into the same issue.
Tried to look at adding something in the RCL's root _ViewImports.cshtml to apply some sort of directory offset, but I wasn't able to find good documentation on the razor directives I can use here.

How to access static content in an MVC Area?

I have an MVC Area in a second Project (part of a different solution) and I cannot seem to find any way of accessing its Static Content when running my website.
Project 1 contains a normal MVC application which works fine.
Project 2 contains simply an Area. Project 2 is using RazorGenerator to compile the views, this project is referenced by Project 1 and is not in the same solution.
In Project 2 within my Area is a Content Folder with static images and styles. How can I get the main website to serve this content? I presume that I cannot because RazorGenerator is not able to compile non code files.
http://forums.asp.net/t/1534837.aspx?Static+content+in+Areas
In articles like above people simply manipulate the URL but this is not working for me, I get 404 for all because its not in the same solution.
How can I get this static content in Project 2 to be accessible to Project 1 given that I am using RazorGenerator to compile my views? I am aiming to make a self contained Area that I can add to other projects without needing to copy files over to support it.

Categories

Resources