I love my Nintendo Switch. It's a brilliant console that fits into my lifestyle. I use it on planes, the kids play it on long car rides, and it's great both portable and docked.
But I never would have predicted "Visual Studio Core for Nintendo Switch" - now that's in a massive pair of air quotes because FUZE4 Nintendo Switchhas no relationship to Microsoft or Visual Studio but it's a really competent coding application that works with USB keyboards! It's an amazing feeling to literally plug in a keyboard and start writing games for Switch...ON A SWITCH! Seriously, don't sleep on this app if you or your kids want to make Switch games.
This is not a complex environment like C++, JAVA or Python. It is positioned as a stepping stone from the likes of Scratch , to more complex real-world ones. In fact everything taught using FUZE is totally applicable in the real-world, it is just that it is presented in a far more accessible, engaging and fun way.
FUZE4 includes a very nice and complete code editor with Syntax Highlighting and Code bookmarks. You can plug in any USB keyboard - I used a Logitech USB keyboard with the USB wireless Dongle! - and you or the children in your life can code away. You just RUN the program with the "start" or + button on the Nintendo Switch.
It can't be overstated how many asserts, bitmaps, sample apps, and 3D models that FUZE4 comes with. You may explore initially and mistakenly think it's a shallow app. IT IS NOT. There is a LOT here. You don't need to make all the assets yourself, and if you're interested in game makers like PICO8 then the idea of making a Switch game with minimal effort will be super attractive to you.
They are also working on FUZE4 Windows as well so stay turned for that! If you register for their forums you can also check out their PDF workbooks and language tutorials. However, if you're like me, you'll have more fun reading the code for the included samples and games and figuring things out from there.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger...With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
I thought this was an interesting and subtle bug behavior that was not only hard to track down but hard to pin down. I wasn't sure 'whose fault it was.'
Here's the story. Feel free to follow along and see what you get.
namespace dotnetlocaletest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(3501.ToWords());
}
}
}
You can see that I want the app to print out the number 3051 as words. Presumably in English, as that's my primary language, but you'll note I haven't indicated that here. Let's run it.
Note that app this works great and as expected in Windows.
scott@IRONHEART:~/dotnetlocaletest$ dotnet run
3501
Huh. It didn't even try. That's weird.
My Windows machine is en-us (English in the USA) but what's my Ubuntu machine?
Looks like it's nothing. It's "C.UTF-8" and it's nothing. C in this context means the POSIX default locate. It's the most basic. C.UTF-8 is definitely NOT the same as en_US.utf8. It's a locate of sorts, but it's not a place.
Fortunately Humanizer 2.7.2 and above has fixed this issue and falls back correctly. Whose "bug" was it? Tough one but in this case, Humanizer had some flawed fallback logic. I updated to 2.7.2 and now C.UTF-8 falls back to a neutral English.
That said, I think it could be argued that WSL/Canonical/Ubuntu should detected my local language and/or set locale to it on installation.
The lesson here is that your applications - especially ones that are expected to work in multiple locales in multiple languages - take "input" from a lot of different places. Phrased differently, not all input comes from the user.
System locale and language, time, timezone, dates, are all input as ambient context to your application. Make sure you assert your assumptions about what "default" is. In this case, my little app worked great on en-US but not on "C.UTF-8." I was able to explore the behavior and learn that there was both a local workaround (I could detected and set a default locale if needed) and there was a library fix available as well.
Assert your assumptions!
Sponsor: Suffering from a lack of clarity around software bugs? Give your customers the experience they deserve and expect with error monitoring from Raygun.com. Installs in minutes, try it today!
Run these commands from PowerShell or PowerShell Core. I recommend PowerShell 6.2.3 or above. You can also use PowerShell on Linux too, so be aware. When you run Install-Module for the first time you'll get a warning that you're downloading and installing stuff from the internet so follow the prompts appropriately.
There's a number of choices for Powerline or Powerline-like prompts from Ubuntu. I like Powerline-Go for it's easy defaults.
I just installed Go, then installed powerline-go with go get.
sudo apt install golang-go
go get -u github.com/justjanne/powerline-go
Add this to your ~/.bashrc. You may already have a GOPATH so be aware.
GOPATH=$HOME/go
function _update_ps1() {
PS1="$($GOPATH/bin/powerline-go -error $?)"
}
if [ "$TERM" != "linux" ] && [ -f "$GOPATH/bin/powerline-go" ]; then
PROMPT_COMMAND="_update_ps1; $PROMPT_COMMAND"
fi
GOTCHA: If you are using WSL2, it'll be lightning fast with git prompts if your source code is in your Ubuntu/Linux mount, somewhere under ~/. However, if your source is under /mnt/c or /mnt anywhere, the git calls being made to populate the prompt are super slow. Be warned. Do your Linux source code/git work in the Linux filesystem for speed until WSL2 gets the file system faster until /mnt.
At this point your Ubuntu/WSL prompt will look awesome as well!
Fonts look weird? Uh oh!
Step Three - Get a better font
If you do all this and you see squares and goofy symbols, it's likely that the font you're using doesn't have the advanced Powerline glyphs. Those glyphs are the ones that make this prompt look so cool!
Then from within Windows Terminal, hit "Ctrl+," to edit your profile.json and change the "fontFace" of your profile or profiles to this:
"fontFace": "DelugiaCode NF",
And that's it!
Remember also you can get lots of Nerd Fonts at https://www.nerdfonts.com/, just make sure you get one (or generate one!) that includes the PowerLine Glyphs.
Have fun!
Sponsor: Suffering from a lack of clarity around software bugs? Give your customers the experience they deserve and expect with error monitoring from Raygun.com. Installs in minutes, try it today!
and I've blogged about "Try .NET" which is a wonderful .NET Core global tool that lets you make interactive in-browser documentation and create workshops that can be run both online and locally (totally offline!)
Even better, you can just clone a Try .NET enabled repository with markdown files that have a few magic herbs and spices, then run "dotnet try" in that cloned folder.
What does this have to do with Polly, the lovely .NET resilience and transient fault handling library that YOU should be using every day? Well, my friends, check out this lovely bit of work by Bryan J Hogan! He's created some interactive workshop-style demos using Try .NET!
How easy is it to check out? Let's give it a try. I've run dotnet tool install --global dotnet-try already. You may need to run update if you've installed it a while back.
That's it. What does it do? It'll launch your browser to a local website powered by Try .NET that looks like this!
Sweet! Ah, but Dear Reader, scroll down! Let me try out one of the examples. You'll see a Monaco-based local text editor (the same edit that powers VS Code) and you're able to run - and modify - local code samples IN THE BROWSER!
Here's the code as text to make it more accessible.
int result = retryPolicy.Execute(() => errorProneCode.QueryTheDatabase());
Console.WriteLine($"Received a response of {result}.");
And the output appears below the sample, again, in a console within the browser:
System.Exception thrown, retrying 1.
System.InsufficientMemoryException thrown, retrying 2.
Received a response of 0.
You can see that Polly gives you a RetryPolicy that can envelop your code and handle things like transient errors, occasional flaky server responses, or whatever else you want it to do. It can be configured as a policy outside your code, or coded inline fluently like this.
NOTE the URL! See that it's a .MD or Markdown file? Try .NET has a special handler that reads in a regular markdown file and executes it. The result is an HTML representation of your Markdown *and* your sample, now executable!
What's the page/image above look like as Markdown? Like this:
# Polly Retries Part 2
### Retrying When an Exception Occurs
The Polly NuGet package has been added and we are going to use the Retry Policy when querying database.
The policy states that if an exception occurs, it will retry up to three times.
Note how you execute the unreliable code inside the policy. `retryPolicy.Execute(() => errorProneCode.QueryTheDatabase());`
#### Next: [Retrying Based on a Result »](./retryIfIncorrectStatus.md) Previous: [Before You Add Polly «](../lettingItFail.md)
Note the special ``` region. The code isn't inline, but rather it lives in a named region in Program.cs in a project in this same repository, neatly under the /src folder. The region is presented in the sample, but as samples are usually more complex and require additional libraries and such, the region name and project context is passed into your app as Try.NET executes it.
Go check out some Try .NET enabled sample repositories. Just make sure you have the Try .NET global tool installed, then go clone and "dotnet try" any of these!
If you're doing classwork, teaching workshops, making assignments for homework, or even working in a low-bandwidth or remote environment this is great as you can put the repositories on a USB key and once they've run once they'll run offline!
Now, be inspired by (and star on GitHub) Bryan's great work and go make your own interactive .NET documentation!
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
I was talking to Tara and we were marveling that in in 1997 15% of Americans had Passports. However, even now less than half do. Consider where the US is physically located. It's isolated in a hemisphere with just Canada and Mexico as neighbors. In parts of Europe a 30 minute drive will find three or four languages, while I can't get to Chipotle in 30 minutes where I live.
A friend who got a passport and went overseas at age 40 came back and told me "it was mind-blowing. There's billions of people who will never live here...and don't want to...and that's OK. It was so useful for me to see other people's worlds and learn that."
I could tease my friend for their awakening. I could say a lot of things. But for a moment consider the context of someone geographically isolated learning - being reminded - that someone can and will live their whole life and never need or want to see your world.
Travel of any kind opens eyes.
Now apply this to technology. I'm a Microsoft technologist today but I've done Java and Mainframes at Nike, Pascal and Linux at Intel, and C and C++ in embedded systems as a consultant. It's fortunate that my technology upbringing has been wide-reaching and steeped in diverse and hybrid systems, but that doesn't negate someone else's bubble. But if I'm going to speak on tech then I need to have a wide perspective. I need to visit other (tech) cultures and see how they live.
You may work for Microsoft, Google, or Lil' Debbie Snack Cakes but just like you should consider getting a passport, you should absolutely visit other (tech) cultures. Travel will make you more well-rounded. Embrace the ever-changing wonders of the world and of technology. Go to their meet-ups, visit their virtual conferences, follow people outside your space, try to build their open source software, learn a foreign (programming) language. They may not want or need to visit yours, but you'll be a better and more well-rounded person when you return home if you're chose to be technology tourist.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
I'm an unabashed Adafruit fan and I often talking about them because I'm always making cool stuff with their hardware and excellent tutorials. You should check out the YouTube video we made when I visited Adafruit Industries in New York with my nephew. They're just a lovely company.
While you're at it, go sign up for the Adabox Subscription and get amazing hardware projects mailed to you in a mystery box regularly!
One of the devices I keep coming back to is the extremely versatile Circuit Playground Express. It's under $25 and does a LOT.
It's got 10 NeoPixels, a motion sensor, temp sensor, light sensor, sound sensor, buttons, a slide, and a speaker. It even can receive and transmit IR for any remote control. It's great for younger kids because you can use alligator clips for the input output pins which means no soldering for easy projects.
You can also mount the Circuit Playground Express onto a Crickit which is the "Creative Robotics & Interactive Construction Kit. It's an add-on lets you #MakeRobotFriend using CircuitPython, MakeCode, or Arduino." The Crickit makes it easy to control motors and adds additional power options to drive them! Great for creating small bots or battlebots as my kids do.
The most significant - and technically impressive, in my opinion - aspect of the Circuit Playground Express is that it doesn't dictate the tech you use! There's 3 great ways to start.
Then, you can use the same board to try CircuitPython, with the Python interpreter running right on the Express.
As you progress, you can advance to using Arduino IDE, which has full support of all the hardware down to the low level, so you can make powerful projects.
Device Simulator Express for Adafruit Circuit Playground Express
Next, check out the Device Simulator Express extension for Visual Studio Code! This was made over the summer by Christella Cidolit, Fatou Mounezo, Jonathan Wang, Lea Akkari, Luke Slevinsky, Michelle Yao, and Rachel Phinnemore, the interns at the Microsoft Garage Vancouver!
This great extension lets YOU, Dear Reader, code for a Circuit Playground Express without the physical hardware! And when you've got one in your hards, it makes development even easier. That means:
Fire up Visual Studio Code with the Device Simulator Express extension installed and then select "Device Simulator Express: New File" in the command palette (CTRL+SHIFT+P to open the palette).
There's a lot of potential here! You've got the simulated device on the right and the Python code on the left. There's step by step debugging in this virtual device. There's a few cool things I can think of to make this extension easier to set up and get started that would be it a killer experience for an intermediate developer who is graduating from MakeCode into a Code editor like VS Code.
It's early days and the interns are back in school but I'm hoping to see this project move forward and get improved. I'll blog more details as I have them!
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
I see this page that says I have no "environments" set up.
I'll make a plan. I changed mine to fall asleep (suspend) in 5 minutes, but the default is 30. Pricing is here.
Now it's making my environment.
I clicked on it. Then opened a new Terminal, ran "dotnet new web" and I'm basically in a thin VS Code, except in the browser. I've got intellicode, I can install the C# extension.
Since I'm running a .NET app I had to run these commands in a new terminal to generate and trust certs for SSL.
Then I hit the Debug menu to build and compile my app IN THE CLOUD and I get "connecting to the forwarded port" as its "localhost" is in the cloud.
Now I've hit a breakpoint! That's bonkers.
Now to try it in VS Code rather than online in the browser. I installed the Visual Studio Online extention and clicked on the little Remote Environment thing on the left side after running VS Code.
This is amazing. Look on the left side there. You can see my Raspberry PI as an SSH target. You can see my new VS Online Plan, you can see my Docker Containers because I'm running Docker for Windows, you can see my WSL Targets as I've got multiple local Linuxes.
Since I'm running currently in VS Online (see the HanselmanTestPlan1 in the lower corner in green) I can just hit F5 and it compiles and runs.
It's a client-server app. VS Code is doing some of the work, but the heavy lifting is in the cloud. Same as if I split the work between Windows and WSL locally, in this case VS Code is talking to that 8 gig Linux Environment I made earlier.
When I hit localhost:500x it's forwarded up to the cloud:
Amazing. Now I can do dev on a little cheapo laptop but have a major server to the work in the cloud. I can then head over to https://online.visualstudio.com/environments and delete it, or I can let it suspend.
I'm going to continue to explore this and see if I can open my blog and podcast sites in this world. Then I can open and develop on them from anywhere. Or soon from my iPad Pro!
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
Jupyter Notebooks has been the significant player in the interactive development space for many years, and Notebooks have played a vital role in the continued popularity of languages like Python, R, Julia, and Scala. Interactive experiences like this give users with a lightweight tool (I like to say "interactive paper") for learning, iterative development, and data science and data manipulation.
Try .NET has grown to support more interactive experiences across the web with runnable code snippets, an interactive documentation generator for .NET Core with the dotnet try global tool, so it makes sense that we take it to the next level, so we're announcing today:
.NET in Jupyter Notebooks
Even better you can start playing with it today, locally or in the cloud!
Please note: If you have the dotnet try global tool already installed, you will need to uninstall the older version and get the latest before grabbing the Jupyter kernel-enabled version of the dotnet try global tool.
Check to see if Jupyter is installed
jupyter kernelspec list
Install the .NET kernel!
dotnet try jupyter install
Test installation
jupyter kernelspec list
You should see the .net-csharp and .net-fsharp listed.
OK, fine maybe they DID teach you this in class. But, you'd be surprised how many people think they know something but don't know the background or the etymology of a term. I find these things fascinating. In a world of bootcamp graduates, community college attendees (myself included!), and self-taught learners, I think it's fun to explore topics like the ones I plan to cover in my new YouTube Series "Computer things they didn't teach you."
BOOK RECOMMENDATION: I think of this series as being in the same vein as the wonderful "Imposter's Handbook" series from Rob Conery (I was also involved, somewhat). In Rob's excellent words: "Learn core CS concepts that are part of every CS degree by reading a book meant for humans. You already know how to code build things, but when it comes to conversations about Big-O notation, database normalization and binary tree traversal you grow silent. That used to happen to me and I decided to change it because I hated being left out. I studied for 3 years and wrote everything down and the result is this book."
Of course it'll take exactly 2 comments before someone comments with "I don't know what crappy school you're going to but we learned this stuff when they handed us our schedule." Fine, maybe this series isn't for you.
In fact I'm doing this series and putting it out there for me. If it helps someone, all the better!
In this first video I cover the concept of Carriage Returns and Line Feeds. But do you know WHY it's called a Carriage Return? What's a carriage? Where did it go? Where is it returning from? Who is feeding it lines?
What would you suggest I do for the next video in the series? I'm thinking Unicode, UTF-8, BOMs, and character encoding.
Sponsor: Octopus Deploy wanted me to let you know that Octopus Server is now free for small teams, without time limits. Give your team a single place to release, deploy and operate your software.
It's no secret I dig WSL (Windows Subsystem for Linux) and now that WSL2 is available in Windows Insiders Slow it's a great time to really explore the options that are available. What I'm finding is so interesting about WSL and how it relates to the Windows system around it is how you can cleanly move data between worlds. This isn't an experience you can easily have with full virtual machines, and it speaks to the tight integration of Linux and Windows.
Look at all this cool stuff you can do when you mix your peanut butter and chocolate!
Run Windows Explorer from Linux and access your distro's files
When you're at the WSL/bash command line and you want to access your files visually, you can run "explorer.exe ." where . is the current directory, and you'll get a Windows Explorer window with your Linux files served to you over a local network plan9 server.
C:\temp> wsl ls -la "/mnt/c/Program Files"
...contents of C:\Program Files...
Use Real Windows commands (not Wine) from Linux
Windows executables are callable/runnable from WSL/Linux because the the Windows Path is in the $PATH until Windows. All you have to do is call it with .exe at the end, explicitly. That's how "Explorer.exe ." works above. You can also notepad.exe, or whatever.exe!
Run Visual Studio Code and access (and build!) your Linux apps natively on Windows
You can run "code ." when you're in a folder within WSL and you'll get prompted to install the VS Remote extensions. That effectively splits Visual Studio Code in half and runs the headless VS Code Server inside Linux with the VS Code client in the Windows world.
Virtual machines are resource intensive and create a very disconnected experience.
The original WSL was very connected, but had fairly poor performance compared to a VM.
WSL 2 brings a hybrid approach with a lightweight VM, a completely connected experience, and high performance.
Again, now available on Windows 10 Insiders Slow.
Run multiple Linuxes in seconds, side by side
Here I'm running "wsl --list --all" and I have three Linuxes already on my system.
C:\Users\scott>wsl --list --all
Windows Subsystem for Linux Distributions:
Ubuntu-18.04 (Default)
Ubuntu-16.04
Pengwin
I can easily run them, and also assign a profile to each so they appear in my Windows Terminal dropdown.
Run an X Windows Server under Windows using Pengwin
Pengwin is a custom WSL-specific Linux distro that's worth the money. You can get it at the Windows Store. Combine Pengwin with an X Server like X410 and you've got a very cool integrated system.
That's it. Get your ideal Linux setup sync'ed on all your systems.
Use the Windows Git Credential Provider within WSL
All of these things culminate in this lovely blog post by Ana Betts where she integrates the Windows Git Credential Provider in WSL by making /usr/bin/git-credential-manager into a shell script that calls the Windows git creds manager. Genius. This would only be possible given this clean and tight integration.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
OK, fine maybe they DID teach you this in class. But, you'd be surprised how many people think they know something but don't know the background or the etymology of a term. I find these things fascinating. In a world of bootcamp graduates, community college attendees (myself included!), and self-taught learners, I think it's fun to explore topics like the ones I plan to cover in my new YouTube Series "Computer things they didn't teach you."
BOOK RECOMMENDATION: I think of this series as being in the same vein as the wonderful "Imposter's Handbook" series from Rob Conery (I was also involved, somewhat). In Rob's excellent words: "Learn core CS concepts that are part of every CS degree by reading a book meant for humans. You already know how to code build things, but when it comes to conversations about Big-O notation, database normalization and binary tree traversal you grow silent. That used to happen to me and I decided to change it because I hated being left out. I studied for 3 years and wrote everything down and the result is this book."
In the first video I covered the concept of Carriage Returns and Line Feeds. But do you know WHY it's called a Carriage Return? What's a carriage? Where did it go? Where is it returning from? Who is feeding it lines?
In this second video I talk about Code Pages, Character Encoding, Unicode, UTF-8 and the BOM. I thought it went very well.
What would you like to hear about next?
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
I've got a lot of different sound devices like USB Headphones, a formal Conference Room Speakerphone for conference calls, and 5.1 Surround Sound speakers, as well as different mics like a nice Shure XLR connected to a PV6 USB Audio Mixer, as well as the built in mics in my webcams and other devices.
There's lots of great audio apps and applets that can improve the audio switching situation on Windows. I like Audio Switcher and the similarly named https://audioswit.ch/er, for example.
But I need to change audio a lot when I'm moving from Teams calls, recording Podcasts, and watching shows. I've got this Elgato Stream Deck that has buttons I can assign to anything. Combine the Stream Deck with the lovely NirCmd utility from NirSoft and I've got one click audio changes!
The icons are just PNGs and there's lots available online. I created a bunch of batch files (*.bat) with contents like this:
nircmdc setdefaultsounddevice "Speakers" 0
and
nircmdc setdefaultsounddevice "Headphones" 0
The last number is 0, 1, or 2 where that means Console, Multimedia, or Communications. You can have one sound device for apps like Netflix and another for apps like Skype that identify as Communications. I just change all defaults, myself.
You can also add in commands like "setsubunitvolumedb" and others to have preset volumes and levels for line-ins. It's ideal for getting reliable results.
Then just use the Stream Deck utility to assign the icon and batch file using the "System | Open" widget. Drag it over and assign and you're set! If you can't figure out what the names of your sound devices are, you can call nircmd showsoundevices.
It just took a few minutes to set this up and it'll save me a bunch of clicks every day.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
My colleague Tara and I were working on prepping a system for Azure IoT development and were using WSL2 on our respective machines. The scripts we were running were long-running and tedious and by the time they were done we basically had a totally customized perfect distro.
Rather than sharing our scripts and having folks run them for hours, we instead decided to export the distro and import it on n number of machines. That way Tara could set up the distro perfectly and then give it to me.
Then I can share the resulting tar and give it to a friend and they can do this! (Note that I'm using ~ which is your home directory from PowerShell. If you're using cmd.exe you'll want to include the full path like c:\users\scott\Appdata\Local\PerfectDistro)
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
I blogged about NancyFX 6 years ago and since then lots of ASP.NET open source frameworks that build upon - and improve! - web development on .NET have become popular.
There's more than one way to serve and angle bracket (or curly brace) my friends!
Jonathan Channon and the Carter Community (JC was a core Nancy contributor as well) have been making a thin layer of extension methods and conventions on top of ASP.NET Core to make URL routing "more elegant." Carter adds and formalizes a more opinionated framework and also adds direct support for the amazing FluentValidation.
One of the best things about ASP.NET Core is its extensibility model and Carter takes full advantage of that. Carter is ASP.NET.
You can add Carter to your existing ASP.NET Core app by just "dotnet add package carter" and adding it to your Startup.cs:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCarter();
}
At this point you can make a quick "microservice" - in this case just handle an HTTP GET - in almost no code, and it's super clear to read:
public class HomeModule : CarterModule
{
public HomeModule()
{
Get("/", async (req, res) => await res.WriteAsync("Hello from Carter!"));
}
}
Or you can add Carter as a template so you can later "dotnet new carter." Start by adding the Carter Template with "dotnet new -i CarterTemplate" and now you can make a new boilerplate starter app anytime.
Carter can also cleanly integrate with your existing ASP.NET apps because, again, it's extensions and improvements on top of ASP.NET. Now how you can add Carter to a ASP.NET Core app that's using Controllers in the MVC pattern just like this:
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
Seriously, though, sometimes folks comment on my busy schedule and I joke that I'm "playing tetris with Outlook" where appointments are falling blocks and I'm twisting and turning them and trying to make it all fit. I also often take some time and actively defrag my calendar.
Defraggging your system's disk usually happens automatically - in the past it didn't - as background processes attempt to "reduce the fragmentation of (a file) by concatenating parts stored in separate locations on a disk." That's a techie explanation.
Here's a basic one. Ever look at your bookshelf and you've got no system? Books all over, no plan. Even worse, imagine someone ripped a book in half along the spine and stored half the book on the top and the rest on the bottom shelf? Why, you'd be scandalized and you'd want to tidy up.
Sometimes folks organize their books by color, sometimes by topic, usually by author. Point is, it can get messy, and you need to take a moment to get organized. The result is a nice tidy bookshelf that has less psychic weight and where the books you want are where you can get to them quickly.
Defragment your schedule
Why not do the same to our calendars? Often we'll just look for an open lot and a 30 min meeting will just drop in there, like an unwanted Tetris piece. If we had more time and energy we might be more aggressive and put the meeting (especially if it's a recurring meeting) in a specific slot.
What slot though? What are we optimizing for? That's up to you, but I'd consider optimizing for context switching - specifically, avoiding context switches before and after meetings.
For example, if you're a coder and you enjoy getting into the flow, avoid putting a meeting in the middle of that flow.
If you are mentoring people - perhaps like me you have a half dozen - then put them all on the same day so your brain is in "mentoring mode." Batch up your code reviews. Make email management an appointment. Is Tuesday creative day? What about No-Meetings Mondays?
Also, make sure you're color coding - just like the defragger! I use categories in my calendar and give meaning to each color so I can easily and quickly tell at a glance if this is a "Balanced Week" or if it's gonna feel weird. If you use colors that clash next to meetings with topics that clash then you can mentally prep yourself for the Context Switch.
What do YOU want your defragmented calendar to look like? Typically it takes just willpower and awareness to defrag your calendar. And just like disk defragmenting, things might run slower for a bit while you're doing it, but the result will be neater and tidier and allow you to be more effective! It'll also, ahem, improve your Outlook.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
VS Code is a great Code Editor but it's not a full IDE (Integrated Development Environment) so there's still lots of reasons for me to use and enjoy Visual Studio on Windows (or Mac).
I wanted to see if it's possible to do 'remote' debugging with WSL and Visual Studio (not Code) and if so, is it something YOU are interested in, Dear Reader.
To start, I've got WSL (specifically WSL2) on my Windows 10 machine. You can get WSL1 today on Windows from "windows features" just by adding it. You can get WSL2 today in the Windows Insiders "Slow Ring."
Then I've got the new Windows Terminal. Not needed for this, but it's awesome if you like the command line.
I'm also using .NET Core with C# for my platform and language of choice. I've installed from https://dot.net/ inside Ubuntu 18.04, under Windows. I've got a web app (dotnet new razor) that runs great in Linux now.
From the WSL prompt within terminal, I can run "explorer.exe ." and it will launch Windows Explorer at the path \\wsl$\Ubuntu-18.04\home\scott\remotewebapp, but VS currently has some issues opening projects across this network boundary. I'll instead put my stuff at c:\temp\remotewebapp and access it from Linux as /mnt/c/temp/remotewebapp.
In a perfect world - this is future speculation/brainstorming, Visual Studio would detect when you opened a project from a Linux path and "Do The Right Thing(tm)."
I'll need to make sure the VSDbg is installed in WSL/Linux first. That's done automatically with VS Code but I'll do it manually in one line like this:
We'll need a launch.json file with enough information to launch the project, attach to it with the debugger, and notice when things have started. VS Code will make this for you. In some theoretical future Visual Studio would also detect the context and generate this file for you. Here's mine, I put it in .vs/launch.json in the project folder.
VS will make a launch.json also but you'll need to add the two most important parts, the $adapter and $adapterArgs part as I have here.
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"$adapter": "C:\\windows\\sysnative\\bash.exe",
"$adapterArgs": "-c ~/vsdbg/vsdbg",
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "/mnt/c/temp/remotewebapp/bin/Debug/netcoreapp3.0/remotewebapp.dll",
"args": [],
"cwd": "/mnt/c/temp/remotewebapp",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
},
"pipeTransport": {
"pipeCwd": "${workspaceRoot}",
"pipeProgram": "bash.exe",
"pipeArgs": [ "-c" ],
"debuggerPath": "~/vsdbg/vsdbg"
},
"logging": { "engineLogging": true }
}
]
}
These launch.json files are used by VS and VS Code and other stuff and give the system and debugger enough to go on. There's no way I know of to automate this next step and attach it to a button like "Start Debugging" - that would be new work in VS - but you can start it like this by calling a VS2019 automation command from the "Command Window" you can access with View | Other Windows | Command Window, or Ctrl-Alt-A.
Once I've typed this once in the Command Window, I can start the next Debug session by just pressing Up Arrow to get the command from history and hitting enter. Again, not perfect, but a start.
Here's a screenshot of me debugging a .NET Core app running in Linux under WSL from Windows Visual Studio 2019.
Thanks to Andy Sterland for helping me get this working.
So, it's possible, but it's not falling-off-a-log automatic. Should this setup and prep be automatic? Is development in WSL from Visual Studio (not Code) something you want? There is great support for Docker development within a container including interactive debugging already, so where do you see this fitting in...if at all? Does this add something or is it more convenient? Would you like "F5" debugging for WSL apps within VS like you can in VS Code?
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
If you could go back and give your 20-something-year-old self some advice, what would you say?
I’m about to graduate and I’m sort of terrified to enter the real world, so I’ve sort of been asking everyone.
What a great question! Off the top of my head - while sitting on the tarmac waiting for takeoff and frantically thumb-typing - I offered this brainstorm.
First
Avoid drama. In relationships and friends
Discard negative people
There’s 8 billion people out there
You don’t have to be friends with them all
Don’t let anyone hold you back or down
We waste hours and days and years with negative people
Collect awesome people like Pokémon
Network your butt off. Talk to everyone nice
Make sure they aren’t transactional networkers
Nice people don’t keep score
They generously share their network
And ask for nothing in return but your professionalism
Don’t use a credit card and get into debt if you can
Whatever you want to buy you likely don’t need it
Get a laptop and an iPad and buy experiences
Don’t buy things. Avoid wanting things
Molecules are expensive
Electrons are basically free
If you can avoid want now, you’ll be happier later
None of us are getting out of this alive
And we don’t get to take any of the stuff
So ask yourself what do I want
What is happiness for you
And optimize your existence around that thing
Enjoy the simple. street food. Good friends
If you don’t want things then you’ll enjoy people of all types
Use a password system like
@1Password
and manage your digital shit tightly
Be focused
And it will be ok
Does this help?
What's YOUR advice to your 20 year old self?
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
Now that .NET Core 3.1 is out jus this last week and it is a "LTS" or Long Term Support version, I thought it'd be a good time to update my main site and my podcast to .NET 3.1. You can read about what LTS means but quite simply it's that "LTS releases are supported for three years after the initial release."
I'm not sure about you, but for me, when I don't look at some code for a few months - in this case because it's working just fine - it takes some time for the context switch back in. For my podcast site and main site I honestly have forgotten what version of .NET they are running on.
and my 3.0 updated csproj. You'll note that most of it is deletions. Also note that I have a custom IISUrlRewrite.xml that I want to make sure gets to a specific place. You'll likely not have anything like this, but be aware.
Some folks are more little methodical about this, upgrading first to 3.0 and then to 3.1. You can feel free to jump all the way if you want. In this case the main breaking changes are from 2.x to 3.x so I'll upgrade the whole thing all in one step.
I compile and run and get an error "InvalidOperationException: Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices(...)." so I'll keep moving through the migration guide, as things change in major versions.
Per the docs, I can remove using Microsoft.AspNetCore.Mvc; and add using Microsoft.Extensions.Hosting; as IHostingEnvironment becomes IWebHostEnvironment. Since my app is a Razor Pages app I'll add a call to servicesAddRazorPages(); as well as calls to UseRouting, UseAuthorization (if needed) and most importantly, moving to endpoint routing like this in my Configure() call.
I also decide that I wanted to see what version I was running on, on the page, so I'd be able to better remember it. I added this call in my _layout.cshtml to output the version of .NET Core I'm using at runtime.
In order versions of .NET, you couldn't get exactly what you wanted from RuntimeInformation.FrameworkDescription, but it works fine in 3.x so it's perfect for my needs.
Finally, I notice that I was using my 15 year old IIS Rewrite Rules (because they work great) but I was configuring them like this:
using (StreamReader iisUrlRewriteStreamReader
= File.OpenText(Path.Combine(env.ContentRootPath, "IISUrlRewrite.xml")))
{
var options = new RewriteOptions()
.AddIISUrlRewrite(iisUrlRewriteStreamReader);
app.UseRewriter(options);
}
And that smells weird to me. Turns out there's an overload on AddIISUrlRewrite that might be better. I don't want to be manually opening up a text file and streaming it like that, so I'll use an IFileProvider instead. This is a lot cleaner and I can remove a using System.IO;
var options = new RewriteOptions()
.AddIISUrlRewrite(env.ContentRootFileProvider, "IISUrlRewrite.xml");
app.UseRewriter(options);
I also did a little "Remove and Sort Usings" refactoring and tidied up both Program.cs and Startup.cs to the minimum and here's my final complete Startup.cs.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace hanselman_core
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/robotstxt", "/Robots.Txt");
});
services.AddMemoryCache();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHealthChecks("/healthcheck");
var options = new RewriteOptions()
.AddIISUrlRewrite(env.ContentRootFileProvider, "IISUrlRewrite.xml");
app.UseRewriter(options);
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
}
And that's it. Followed the migration, changed a few methods and interfaces, and ended up removing a half dozen lines of code and in fact ended up with a simpler system. Here's the modified files for my update:
❯ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Pages/Index.cshtml.cs
modified: Pages/Shared/_Layout.cshtml
modified: Program.cs
modified: Startup.cs
modified: hanselman-core.csproj
Updating the Web Site in Azure App Service and Azure DevOps
That all works locally, so I'll check in in and double check my Azure App Service Plan and Azure DevOps Pipeline to make sure that the staging - and then production - sites are updated.
ASP.NET Core apps can rely on a runtime that is already installed in the Azure App Service or one can do a "self contained" install. My web site needs .NET Core 3.1 (LTS) so ideally I'd change this dropdown in General Settings to get LTS and get 3.1. However, this only works if the latest stuff is installed on Azure App Service. At some point soon in the future .NET Core 3.1 will be on Azure App Service for Linux but it might be a week or so. At the time of this writing LTS is still 2.2.7 so I'll do a self-contained install which will take up more disk space but will be more reliable for my needs and will allow me full controll over versions.
I am running this on Azure App Service for Linux so it's running in a container. It didn't startup so I checked the logs at startup via the Log Stream and it says that the app isn't listening on Port 8080 - or at least it didn't answer an HTTP GET ping.
I wonder why? Well, I scrolled up higher in the logs and noted this error:
2019-12-10T18:21:25.138713683Z The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
Oops! Did I make sure that my csproj was 3.1? Turns out I put in netcoreapp3.0 even though I was thinking 3.1! I updated and redeployed.
It's important to make sure that your SDK - the thing that builds - lines up with the the runtime version. I have an Azure DevOps pipeline that is doing the building so I added a "use .NET Core SDK" task that asked for 3.1.100 explicitly.
Again, I need to make sure that my Pipeline includes that self-contained publish with a -r linux-x64 parameter indicating this is the runtime needed for a self-contained install.
Now my CI/CD pipeline is building for 3.1 and I've set my App Service to run on 3.1 by shipping 3.1 with my publish artifact. When .NET Core 3.1 LTS is released on App Service I can remove this extra argument and rely on the Azure App Service to manage the runtime.
All in all, this took about an hour and a half. Figure a day for your larger apps. Now I'll spend another hour (likely less) to update my podcast site.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
My podcast has historically run on ASP.NET Core on Azure App Service for Windows. How do I know if it'll run on Linux? Well, I'll try it see!
I use WSL (Windows Subsystem for Linux) and so should you. It's very likely that you have WSL ready to go on you machine and you just haven't turned it on. Combine WSL (or the new WSL2) with the Windows Terminal and you're in a lovely spot on Windows with the ability to develop anything for anywhere.
First, let's see if I can run my existing ASP.NET Core podcast site (now updated to .NET Core 3.1) on Linux. I'll start up Ubuntu 18.04 on Windows and run dotnet --version to see if I have anything installed already. You may have nothing. I have 3.0 it seems:
$ dotnet --version
3.0.100
Ok, I'll want to install .NET Core 3.1 on WSL's Ubuntu instance. Remember, just because I have .NET 3.1 installed in Windows doesn't mean it's installed in my Linux/WSL instance(s). I need to maintain those on my own. Another way to think about it is that I've got the win-x64 install of .NET 3.1 and now I need the linux-x64 one.
NOTE: It is true that I could "dotnet publish -r linux-x64" and then scp the resulting complete published files over to Linux/WSL. It depends on how I want to divide responsibility. Do I want to build on Windows and run on Linux/Linux? Or do I want to build and run from Linux. Both are valid, it just depends on your choices, patience, and familiarity.
I'll head over to https://dotnet.microsoft.com/download and get .NET Core 3.1 for Ubuntu. If you use apt, and I assume you do, there's some preliminary setup and then it's a simple
sudo apt-get install dotnet-sdk-3.1
No sweat. Let's "dotnet build" and hope for the best!
It might be surprising but if you aren't doing anything tricky or Windows-specific, your .NET Core app should just build the same on Windows as it does on Linux. If you ARE doing something interesting or OS-specific you can #ifdef your way to glory if you insist.
Bonus points if you have Unit Tests - and I do - so next I'll run my unit tests and see how it goes.
OPTION: I write things like build.ps1 and test.ps1 that use PowerShell as PowerShell is on Windows already. Then I install PowerShell (just for the scripting, not the shelling) on Linux so I can use my .ps1 scripts everywhere. The same test.ps1 and build.ps1 and dockertest.ps1, etc just works on all platforms. Make sure you have a shebang #!/usr/bin/pwsh at the top of your ps1 files so you can just run them (chmod +x) on Linux.
I run test.ps1 which runs this command
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:CoverletOutput=./lcov .\hanselminutes.core.tests
with coverlet for code coverage and...it works! Again, this might be surprising but if you don't have any hard coded paths, make any assumptions about a C:\ drive existing, and avoid the registry and other Windows-specific things, things work.
Test Run Successful.
Total tests: 23
Passed: 23
Total time: 9.6340 Seconds
I can build, I can test, but can I run it? What about running and testing in containers?
I'm running WSL2 on my system and I've doing all this in Ubuntu 18.04 AND I'm running the Docker WSL Tech Preview. Why not see if I can run my tests under Docker as well? From Docker for Windows I'll enabled the Experimental WSL2 support and then from the Resources menu, WSL Integration I'll enable Docker within my Ubuntu 18.04 instance (your instances and their names will be your own).
I can confirm it's working with "docker info" under WSL and talking to a working instance. I should be able to run "docker info" in BOTH Windows AND WSL.
Cool. I remembered I also I needed to update my Dockerfile as well from the 2.2 SDK on the Docker hub to the 3.1 SDK from Microsoft Container Registry, so this one line change:
#FROM microsoft/dotnet:2.2-sdk AS build
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build
as well as the final runtime version for the app later in the Dockerfile. Basically make sure your Dockerfile uses the right versions.
#FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
I also volume mount the tests results so there's this offensive If statement in the test.ps1. YES, I know I should just do all the paths with / and make them relative.
#!/usr/bin/pwsh
docker build --pull --target testrunner -t podcast:test .
if ($IsWindows)
{
docker run --rm -v d:\github\hanselminutes-core\TestResults:/app/hanselminutes.core.tests/TestResults podcast:test
}
else
{
docker run --rm -v ~/hanselminutes-core/TestResults:/app/hanselminutes.core.tests/TestResults podcast:test
}
Regardless, it works and it works wonderfully. Now I've got tests running in Windows and Linux and in Docker (in a Linux container) managed by WSL2. Everything works everywhere. Now that it runs well on WSL, I know it'll work great in Azure on Linux.
The short version is, make a Linux App Service Plan (remember that an "App Service Plan " is a VM that you don't worry about. See in the pick below that the Linux Plan has a penguin icon. Also remember that you can have as many apps inside your plan as you'd like (and will fit in memory and resources). When you select a "Stack" for your app within Azure App Service for Linux you're effectively selecting a Docker Image that Azure manages for you.
I started by deploying to staging.mydomain.com and trying it out. You can use Azure Front Door or CloudFlare to manage traffic and then swap the DNS. I tested on Staging for a while, then just changed DNS directly. I waited a few hours for traffic to drain off the Windows podcast site and then stopped it. After a day or two of no traffic I deleted it. If I did my job right, none of you noticed the site moved from Windows to Linux, from .NET Core 2.2 to .NET Core 3.1. It should be as fast or faster with no downtime.
Here's a snap of my Azure Portal. As of today, I've moved my home page, my blood sugar management portal, and my podcast site all onto a single Linux App Service Plan. Each is hosted on GitHub and each is deploying automatically with Azure DevOps.
What cool migrations have YOU done lately, Dear Reader?
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!
Setting up on Azure DevOps is easy and just like signing up for Azure you'll use your Microsoft ID. Mine is my gmail/gsuite, in fact. You can also login with GitHub creds. It's also nice if your project makes NuGet packages as there's an integrated NuGet Server that others can consume libraries from downstream before (if) you publish them publicly.
There's some controversy as some folks REALLY like the "classic" pipeline while others like the YAML (Yet Another Markup Language, IMHO) style. YAML doesn't have all the features of the original pipeline yet, but it's close. It's primary advantage is that the pipeline definition exists as a single .YAML file and can be checked-in with your source code. That way someone (you, whomever) could import your GitHub or DevOps Git repository and it includes everything it needs to build and optionally deploy the app.
The Azure DevOps team is one of the most organized and transparent teams with a published roadmap that's super detailed and they announce their sprint numbers in the app itself as it's updated which is pretty cool.
When YAML includes a nice visual interface on top of it, it'll be time for everyone to jump but regardless I wanted to make my sites more self-contained. I may try using GitHub Actions at some point and comparing them as well.
Migrating from Classic Pipelines to YAML Pipelines
If you have one, you can go to an existing pipeline in DevOps and click View YAML and get some YAML that will get you most of the way there but often includes some missing context or variables. The resulting YAML in my opinion isn't going to be as clean as what you can do from scratch, but it's worth looking at.
In decided to disable/pause my original pipeline and make a new one in parallel. Then I opened them side by side and recreated it. This let me learn more and the result ended up cleaner than I'd expected.
The YAML editor has a half-assed (sorry) visual designer on the right that basically has Tasks that will write a little chunk of YAML for you, but:
Once it's placed you're on your own
You can't edit it or modify it visually. It's text now.
If your cursor has the insert point in the wrong place it'll mess up your YAML
It's not smart
But it does provide a catalog of options and it does jumpstart things. Here's my YAML to build and publish a zip file (artifact) of my podcast site. Note that my podcast site is three projects, the site, a utility library, and some tests. I found these docs useful for building ASP.NET Core apps.
You'll see it triggers builds on the main branch. "Main" is the name of my primary GitHub branch. Yours likely differs.
It uses Ubuntu to do the build and it builds in Release mode. II
I install the .NET 3.1.x SDK for building my app, and I build it, then run the tests based on a globbing *tests pattern.
I do a self-contained publish using -r linux-x64 because I know my target App Service is Linux (it's cheaper) and it goes to the ArtifactStagingDirectory and I name it "hanselminutes." At this point it's a zip file in a folder in the sky.
Next I move to the release pipeline. Now, you can also do the actual Azure Publish to a Web App/App Service from a YAML Build Pipeline. I suppose that's fine if your site/project is simple. I wanted to have dev/test/staging so I have a separate Release Pipeline.
The Release Pipelines system in Azure DevOps can pull an "Artifact" from anywhere - GitHub, DevOps itself natch, Jenkins, Docker Hub, whatever. I set mine up with a Continuous Deployment Trigger that makes a new release every time a build is available. I could also do Releases manually, with specific tags, scheduled, or gated if I'd liked.
Mine is super easy since it's just a website. It's got a single task in the Release Pipeline that does an Azure App Service Deploy. I can also deploy to a slot like Staging, then check it out, and then swap to Production later.
There's nice integration between Azure DevOps and the Azure Portal so I can see within Azure in the Deployment Center of my App Service that my deployments are working:
I've found this all to be a good use of my staycation and even though I'm just a one-person company I've been able to get a very nice automated build system set up at very low cost (GitHub free account for a private repo, 1800 free Azure DevOps minutes, and an App Service for Linux plan) A basic starts at $13 with 1.75Gb of RAM but I'm planning on moving all my sites over to a single big P1v2 with 3.5G of RAM and an SSD for around $80 a month. That should get all of my ~20 sites under one roof for a price/perf I can handle.
Sponsor: Like C#? We do too! That’s why we've developed a fast, smart, cross-platform .NET IDE which gives you even more coding power. Clever code analysis, rich code completion, instant search and navigation, an advanced debugger... With JetBrains Rider, everything you need is at your fingertips. Code C# at the speed of thought on Linux, Mac, or Windows. Try JetBrains Rider today!