Using webpack in combination with Web Forms - c#

I have a webpack configuration that ties together all the dependencies for my web app. The web app is pretty old and is made using Web Forms. I'm going away from using the built in .NET minifier and bundle loader, and instead, towards using webpack's vendor packages etc.
My issue is that the web app is served out of a virtual directory, so I need to be able to reliably locate all required *.js files at runtime for the web app. In my mind I reckon this looks like webpack "somehow" producing an output of what files it has written (including hashes etc), then somehow putting this into my master pages or something. I know there is the HTML plugin for webpack but I don't know how to wrangle that to just produce a list of the *.js files, or if thats even on the right track.
How can I load my webpack'd *.js and *.css files from within Web Forms?

First, you need to install assets-webpack-plugin and configure it in your webpack. You can access this package here in npmjs.org
Why Is This Useful?
When working with Webpack you might want to generate your bundles with a generated hash in them (for cache busting). This plug-in outputs a json file with the paths of the generated assets so you can find them from somewhere else.
There is a good tutorial here to adding styles and scripts dynamically in ASPX.
{
"one": {
"js": "/js/one_2bb80372ebe8047a68d4.bundle.js"
},
"two": {
"js": "/js/two_2bb80372ebe8047a68d4.bundle.js"
}
}
In your aspx or master-page of your web-forms, you can easily deserilize this JSON and load your script and style assets in your page.
I'm using assets-webpack-plugin in my MVC project and I'm sure it wouldn't be a problem to use it in ASPX WebForms.

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.

Writing chrome extension in C#?

Today I started looking at the Chrome extensions the first time ever, I have a very silly questions, I am sure the answer is NO to this as per google search but I just wanted to make sure from the community here.
Is it possible to use C# to write code instead of javascript?
Is it possible to use Partial Views (ASP.NET MVC) in chrome extension as it renders HTML?
I found this in VS Marketplace
https://marketplace.visualstudio.com/items?itemName=MadsKristensen.GoogleChromeExtensionProjectTemplate Is there any other templates which have bootstrap etc
Cheers
You can create browser extension with C#.
Specifically, Using Client-side Blazor.
To publish, the following operations are required.
First, you publish like normal standalone app.
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/blazor/webassembly?view=aspnetcore-3.1#standalone-deployment
Then, Remove the underscore from directory name. Since it cannot be used in the extension.
# remove underbar from directory name
mv _framework/_bin _framework/bin
mv _framework framework
# rewrite
sed 's/_bin/bin/g' framework/blazor.webassembly.js
sed 's/_framework/framework/g' framework/blazor.webassembly.js index.html
Then, Add manifest.json and setting CSP like this,
"content_security_policy": "script-src 'self' 'unsafe-eval' 'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA='; object-src 'self'",
Blazor boot script add script tag to html, so you should add scripts hash to allow execute bootup script.
This is sample app I created.
https://github.com/key-moon/WeatherForecastExtensionWithBlazor
And, This is commentary (wrote in Japanese).
https://qiita.com/keymoon/items/03357e58eddf75871527
You can definitely create a Chrome Extension (fairly) easily using C# now with the help of Blazor WebAssembly.
If you are still interested in trying out or if anyone else is interested, I have created a package in the repository Blazor.BrowserExtension. Just follow the steps in the link to create the project.
With this package, you get the things that you need in an extension. Currently it supports Background, Popup (Browser Action), Options page and even Content Scripts (extra setup required). Just build the project and then you can load the unpacked extension from the output of the build.
Chrome Extensions API are accessible in Razor pages or from dependency injection. The APIs are imported from another package WebExtension.Net.
Yes you can write Chrome extension in C#, and it's easy.
I tried the below. It was fast and works right away:
Run dotnet new --install Blazor.BrowserExtension.Template.
Run dotnet new browserext --name to initialize a new project with the template.
Change the working directory into the newly created project directory.
Run dotnet build to build the project.
On Google Chrome:
Launch the Extensions page ( ⋮ → More tools → Extensions).
Switch on Developer mode.
Click on the Load unpacked button, then navigate to %ProjectDir%\bin\Debug\net5.0\ and select the foler browserextension.
Source: https://github.com/mingyaulee/Blazor.BrowserExtension
Thank you very much to "mingyaulee" for such an awesome work and sharing it.
UPDATES:
You can use C# based https://github.com/mingyaulee/Blazor.BrowserExtension project and build your chrome extension distributable.
ORIGINAL ANSWER:
Chrome Extension runs in the browser so you can not use C# in Chrome Extension Development.
Again the Chrome extension runs in the browser so you can not use ASP.NET MVC in Chrome Extension Development, but you can use ASP.NET MVC or any other language at server to generate the views and render them in the chrome extension using ajax.
Have a look at this: https://github.com/Ehesp/Chrome-Extension-Twitter-Bootstrap-3-Template
Technically, you can use a C# binary as a Native Host that talks to the JavaScript portion in the browser.
However, that would complicate your extension distribution, as you can't bundle the two to CWS; the native host component has to be separately installed.
This should only be used when you have legitimate reason to do something that's impossible within the browser sandbox.
Using Blazor and write it as normal html/css maybe? You still need to build blazor project though but I think it count as technically possible to write extension in C#

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