In this follow-up, I’m going to cover how this can be used in conjunction with npm in order to simply move the files into the correct location. Note that this is a new tool in Visual Studio, and you’ll need VS 15.8.0 or higher for it to work. Let’s start by creating an empty .Net Core Web App. Once you’ve done so, you’re app probably looks like this:
Now you’ll need to launch a bash or powershell console:
npm install jquery
Refresh your project and show all files:
As you can see, you now have a node_modules directory. The problem is that the files need to be under wwwroot. Obviously, you could copy it, but let’s try the client side manager:
In the resultant dialog, select File System; navigate to the JQuery directory and select the files that you want:
Now refresh the project again and let’s see what we have:
This actually translates to a JSON file; libman.json looks like this:
Okay – so that’s very nice; but now that we have a system that will copy files from wherever into wherever (the rule is that you have to go deeper in the files structure – so you couldn’t copy that file back again) then we, presumably, could use this for other things. For example, have you ever had a file (an image or something) that you need to include in your project:
Obviously, c:\tmp above could just as easily be \\shareddrive\images.
To be clear, I’m unsure whether this is abusing the system, or it was meant for this exact thing. It is possible that this type of usage may become unsupported in future (so you’ve been warned).
As a relative newcomer to the web front-end, one thing that always surprised me was how many moving parts you need to get something running. This is probably true elsewhere (i.e. in back-end development, and desktop development) but we just do a better job of hiding it. In the past, people writing web-pages have always has an uneasy relationship with Microsoft. Maybe it started in the late nineties when, in order to win the battle of the browsers with Netscape, Microsoft started giving its product away. Since then IE became more and more bloated, as it had to support 10 years worth of old technology, and people have had to ensure it still worked on IE 6 and 7.
But now things are different, Microsoft is a rebranded company and nobody hates them anymore… and when you create a brand new Asp.Net Core 2.1 project, you can use npm to install client side packages, use them in your web page and it all just works – end of the post.
Except that hasn’t happened. In fact, the client side package management for the web seems (to me) to be in a bit of a mess – especially where Microsoft is concerned.
Create a brand new Asp.Net Core 2.1 MVC project from the template and it comes with jquery, supplied by bower; except Microsoft aren’t continuing support for bower anymore.
So, use NuGet to install your package?
Nope – not on .Net Core!
So, use npm – that’s still supported?
Yep – here’s the Asp.Net Signal R client side package installed using npm:
Okay, so it puts it in ‘node_modules’ – I can reference the library directly from there, right?
Nope – it needs to be in wwwroot\lib.
Errr – so I copy it across manually?
You can. Although that’s kind of the problem that package managers were invented to solve.
I can create a gulp task to take the files out of the downloaded directory and place them into the lib directory!
Yes – yes, you can. Although now you have a gulp task, and an npm restore, all so that you can include one or two files in your project. This all just seems too hard!
Introducing LibMan. It isn’t a Package Manager; but it might just be the correct answer to the question: “Why the hell is this whole thing so difficult – I only want one file!”
Here is the context menu for the in the lib folder after v15.8 (this has been available in preview for a while):
That gives you the following dialog:
This is amazing, I can pick the library that I want, and where I want it to go! I can also select specific files that I want – this almost feels like a sensible way to manage client side packages. Click install and bang:
You can see what it’s done by either selecting “Manage Client Side Packages…” from the solution context menu:
Alternatively, you can just have a look at the libman.json file (they both do the same thing as of 15.8.7, which makes me wonder whether “Manage Client Side Packages…” will do something different one day – the ellipses kind of give it away).
And There’s More…
There’s a CLI for it (which seemed to balk a bit when I tried to install it via NuGet), and you can use this as a replacement for Gulp to copy files around, by just selecting “File System” as the source (although this sort of solves that problem further down the tree).
One way that your web-site might be vulnerable to an attack is via Cross Site Request Forgery (CSRF or XSRF).
If you’ve ever been logged into a web-site – say Twitter for example – and you open a separate tab, then type in a twitter account, for example: https://www.twitter.com/paul_michaels, you’ll notice that when the site opens, it opens already logged in for you – which is very helpful. Imagine having to re-log-in every single time you wanted to view a tweet or a profile.
Okay, now imagine that, instead of typing that into the browser, you click the link above – try it! What – it didn’t take you to Twitter, but it took you to the home page of this blog? In fact, that’s exactly how a CSRF attack would work in practice. If you were already logged into that site, the link could have executed a CSRF attack.
Cross Site Request Forgery works on the premise that the victim of the attack is actually logged into a given website with valid credentials, and the attacker knows the exact format of a valid request. So, for example, I can take you to my Twitter profile, because the format of that is well known. Nobody, least of all Twitter themselves, want you to have to mess around logging in again.
But what about if you want to actually post a Tweet? Here’s the Url that gets called:
It’s a little difficult to demonstrate, because Twitter operates over HTTPS, so the traffic is encrypted, but the gist is that, even if I managed to create a site that copied this message exactly, the Tweet would not get created. Let’s have a look at replicating such an attack.
Your first step is to create a really bog standard web site – the default MVC template will do. It might also help to demonstrate if you don’t use HTTPS.
Launch the web-site with F12 tools and make a given request. For example, click the “Contact” link on the default site. Make a note of the URL and the form data for the request:
Obviously, don’t use that code – otherwise you’ll cause over a thousand pounds to be transferred from my account to yours! Replace the URL with whatever the URL from the above site was, and the values with whatever values were behind your grey box above. You can use POST or GET or whatever else you like. What you’ll notice is that clicking your button interacts with the site you created in the same way as it would if you were on your site. The “SendLoadsOfMoney” is obviously an example that takes it to the extremes, but the principle is correct.
To fix this in MVC is very easy.
If you add this to the controller method, you should start seeing this error:
The required anti-forgery cookie “__RequestVerificationToken” is not present.
So far, so good. This works for Asp.Net Mvc Core and Framework, but not for ApiControllers! The decorator [ValidateAntiForgeryToken] has no effect on an ApiController out of the box (and worse, you’ll never know it without launching a specific attack on your ApiController). So what can you do?
One option is to implement a custom token as described here. I would treat this as a specific case for ApiControllers only, though.