I got an interesting email today. The author said "I have a problem consuming a .net core class library in a winforms project and can't seem to find a solution." This was interesting for a few reasons. First, it's solvable, second, it's common, and third, it's a good opportunity to clear a few things up with a good example.
To start, I emailed back with "precision questioning." I needed to assert my assumptions and get a few very specific details to make sure this was, in fact, possible. I said. "What library are you trying to use? What versions of each side (core and winforms)? What VS version?"
The answer was "I am working with VS2017. The class library is on NETCoreApp 1.1 and the app is a Winforms project on .NET Framework 4.6.2."
Cool! Let's solve it.
Referencing a .NET Core library from WinForms (running .NET Full Framework)
Before we parse this question. Let's level-set.
.NET is this big name. It's the name for the whole ecosystem, but it's overloaded in such a way that someone can say "I'm using .NET" and you only have a general idea of what that means. Are you using it on mobile? in docker? on windows?
Let's consider that ".NET" as a name is overloaded and note that there are a few "instances of .NET"
.NET (full) Framework - Ships with Windows. Runs ASP.NET, WPF, WinForms, and a TON of apps on Windows. Lots of businesses depend on it and have for a decade. Super powerful. Non-technical parent maybe downloads it if they want to run paint.net or a game.
.NET Core - Small, fast, open source, and cross-platform. Runs not only on Windows but also Mac and a dozen flavors of Linux.
Xamarin/Mono/Unity - The .NET that makes it possible to write apps in C# or F# and run them on everything from an iPad to cheap Android phone to a Nintendo Switch.
All of these runtimes are .NET. If you learn C# or F# or VB, you're a .NET Programmer. If you do a little research and google around you can write code for Windows, Mac, Linux, Xbox, Playstation, Raspberry Pi, Android, iOS, and on and on. You can run apps on Azure, GCP, AWS - anywhere.
What's .NET Standard?
.NET Standard isn't a runtime. It's not something you can install. It's not an "instance of .NET." .NET Standard is an interface - a versioned list of APIs that you can call. Each newer version of .NET Standard adds more APIs but leaves older platforms/operating systems behind.
The runtimes then implement this standard. If someone comes out with a new .NET that runs on a device I've never heard of, BUT it "implements .NET Standard" then I just learned I can write code for it. I can even use my existing .NET Standard libraries. You can see the full spread of .NET Standard versions to supported runtimes in this table.
Now, you could target a runtime - a specific .NET - or you can be more flexible and target .NET Standard. Why lock yourself down to a single operating system or specific version of .NET? Why not target a list of APIs that are supported on a ton of platforms?
The person who emailed me wanted to "run a .NET Core Library on WinForms." Tease apart that statement. What they really want is to reuse code - a dll/library specifically.
When you make a new library in Visual Studio 2017 you get these choices. If you're making a brand new library that you might want to use in more than one place, you'll almost always want to choose .NET Standard.
.NET Standard isn't a runtime or a platform. It's not an operating system choice. .NET Standard is a bunch of APIs.
Next, check properties and decide what version of .NET Standard you need.
You can check out .NET Standard 1.6, for example, and see all the namespaces and methods it supports. It works on Windows 10, .NET Framework 4.6.1 and more. If you need to make a library that works on Windows 8 or an older .NET Framework like 4.5, you'll need to choose a lower .NET Standard version. The table of supported platforms is here.
From the docs - When choosing a .NET Standard version, you should consider this trade-off:
The higher the version, the more APIs are available to you.
The lower the version, the more platforms implement it.
In general, we recommend you to target the lowest version of .NET Standard possible. The goal here is reuse. You can also check out the Portability Analyzer and run it on your existing libraries to see if the APIs you need are available.
.NET Standard is what you target for your libraries, and the apps that USE your library target a platform.
I emailed them back briefly, "Try making the library netstandard instead."
They emailed back just a short email, "Yes! That did the trick!"
Sponsor: Big thanks to Raygun! Don't rely on your users to report the problems they experience. Automatically detect, diagnose and understand the root cause of errors, crashes and performance issues in your web and mobile apps. Learn more.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
There's opinionated frameworks, and then there's opinionated frameworks that also respect your opinion. LLBLGen is one of those. For many years it's been a great entity modeling tool as well as an excellent ORM (Object Relational Mapper.) It also supports all major ORMs in the .NET space like Entity Framework, NHibernate, Linq to Sql as well as, of course, their own included LLBLGen Pro Runtime Framework. It works with VS2015 and VS2017 and is actively supported and extremely actively developed. It's because of that active development that I wanted to check it out. It's got Getting Started videos and a TON of docs, so I figured I could do some damage pretty quickly with a 30 day trial.
NOTE: Just a reminder, I don't do sponsored posts for software. I just felt like checking out LLBLGen because it's been a few years since I looked at it least. All my observations are my own, unfiltered, as I know you like them, Dear Reader.
You can do Database First - a technique that is crucial for so many of us with existing databases but often downplayed with other ORMs - as well as Model First and then generate classes.
I decided to start with one of the newer SQL Server 2016 sample databases called Worldwide Importers. There's localdb versions, Azure SQL Database versions, and SQL Server 2016 backups. I made a database in Azure, uploaded a "bacpac" file to Azure storage, and imported the database into SQL Azure. Although I certainly could have done the work locally, I can get more horsepower in the cloud.
When I make a new Project in the LLBLGen GUI I can pick from a ton of different ORMs including 5 (!) versions of Entity Framework including EFCore, as well as NHibernate 4v and Linq to SQL (which is a nice touch as I have two L2S projects still in production.)
The WorldWide Importers sample is a nice one as it's typical and non-trivial in complexity. I pointed LLBLGen at it and let it rip. Make sure you wait until your database is totally restored into SQL Azure or your SQL Server or you may get weird errors about Zombie Transactions.
When it's done, you'll get an Errors & Warnings pane that will tell you how many stored procs, tables, views, etc that were imported, and that they are "unmapped," which is cool since you haven't mapped them.
You can switch your Target ORM Framework after you've imported your Data Model, but you really should put a little thought into how your database is structured and whether or not your preferred ORM supports all the features you (may) have used heavily in your Database. For example, if you're a very "stored proc"-style shop, it would be a problem if you really wanted to use an ORM that didn't support stored procs.
LLBLGen is rather extraordinary in that it not only has smarts about what's possible and what's not, but it also offers you a multiple-choice solution framework when something is wrong. For example, there's a mapping here that isn't support, so it's offering me three options to fix it, including (of course) changing the offending entity by changing/adding fields.
Once you have a valid model and have corrected any issues and/or made appropriate changes, you can Generate Source Code for your target platform, language, and ORM Framework.
Make no mistake about it - there's a LOT of depth here. There's multiple kinds of templates and tons of options. You may not get it all right on the first try, but it's very forgiving. Just remember where the authoritative source of truth is. Is your model the truth? Or your database? As you move forward (depending on where you started) your source of truth will likely change. You can use any of the many code generators or expand them with your own modifications and metadata.
You'll also likely get addicted to the nice visual editors for entities (a good thing!).
Quick Model is also nice if you want to visualize (and change) relationships between just a few of your many tables.
If you get fast enough, with practice you can use the Quick Model editor and it's Command Input palette to model most of a new database when interviewing domain experts. The visual designer is fast and flexible.
I've truly barely scratched the surface of this deep tool. The pricing is very reasonable considering all it does.
Have you used LLBLGen or similar tools lately? What's been your impression?
Sponsor: Big thanks to Raygun! Don't rely on your users to report the problems they experience. Automatically detect, diagnose and understand the root cause of errors, crashes and performance issues in your web and mobile apps. Learn more.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
Also, have a simple downloadable .tar.gz which expands into /bin + /lib + /examples. I loved C# back in my Windows days and I moved to Linux to escape Microsoft complexities and over-reliance on complex IDEs and tools, scattered like shrapnel all over my c:/
I will not run apt-get against your repo without knowing ahead of time what I'm getting and where will it all go, so let me play with the tarball first.
This is a great point, and we're going to look at revamping and simplifying the http://dot.net/core with this in mind in the next few weeks. They're saying that the Linux instructions, like these instructions on installing .NET Core on Ubuntu for example, make you trust a 3rd party apt repro and apt-get .NET, while they want a more non-committal option. This gets to the larger "the website is getting bigger than it needs to be and confusing" point.
NOTE: You MAY need to apt-get install libunwind8 if you get an error like "Failed to load /home/ubuntu/teste-dotnet-rc2/libcoreclr.so, error: libunwind.so.8: cannot open shared object file: No such file or directory" but libunwind isn't very controversial.
Once you've unziped/tar'd it into a local folder, just be sure to run dotnet from that folder.
Desktop $ mkdir dotnetlinux Desktop $ cd dotnetlinux/ dotnetlinux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.2 LTS Release: 16.04 Codename: xenial dotnetlinux $ curl -o dotnet.tar.gz https://download.microsoft.com/download/E/7/8/E782433E-7737-4E6C-BFBF-290A0A81C3D7/dotnet-dev-ub untu.16.04-x64.1.0.4.tar.gz dotnetlinux $ tar -xvf dotnet.tar.gz dotnetlinux $ cd /mnt/c/Users/scott/Desktop/localdotnettest/ localdotnettest $ ../dotnetlinux/dotnet new console Content generation time: 103.842 ms The template "Console Application" created successfully. localdotnettest $ ../dotnetlinux/dotnet restore Restoring packages for /mnt/c/Users/scott/Desktop/localdotnettest/localdotnettest.csproj... localdotnettest $ ../dotnetlinux/dotnet run Hello World!
The more interesting "samples" are the templates you have available to you from "dotnet new."
localdotnettest $ /mnt/c/Users/scott/Desktop/dotnetlinux/dotnet new *SNIP*
Templates Short Name Language Tags ---------------------------------------------------------------------- Console Application console [C#], F# Common/Console Class library classlib [C#], F# Common/Library Unit Test Project mstest [C#], F# Test/MSTest xUnit Test Project xunit [C#], F# Test/xUnit ASP.NET Core Empty web [C#] Web/Empty ASP.NET Core Web App mvc [C#], F# Web/MVC ASP.NET Core Web API webapi [C#] Web/WebAPI Solution File sln Solution
Examples: dotnet new mvc --auth None --framework netcoreapp1.1 dotnet new classlib dotnet new --help
From here you can "dotnet new web" or "dotnet new console" using your local dotnetbefore you decide to commit to installing .NET Core from an apt repo or yum or whatever.
Sponsor: Check out Seq: simple centralized logging, on your infrastructure, with great support for ASP.NET Core and Serilog. Download version 4.0.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
Eight years ago I stumbled on the husk of an old arcade cabinet and along with my buddy John Batdorf, proceeded to reclaim the cabinet, refinish, paint, and turn it into a proper MAME (Multi-Arcade Machine Emulator)
Last week I build a RetroPie into an X-arcade tankstick. This is my best retro arcade yet because it's got HDMI out and I can take it to friends' houses. That said, I'm going to briefly go over my other systems because they may be more attractive for your needs. If you have no patience, scroll down.
A full size MAME Cabinet - The Complete MAME Cabinet How-To
When I made my first MAME cabinet I put a small "Shuttle PC" inside. The MAME system is in my office and runs to this day on Windows 7 with a HyperSpin frontend.
Software Disclaimer 1: There's all sorts of iffy legal issues around emulating arcade games with boards/ROMs you don't own. This series of posts has nothing to do with that. I do own some original arcade boards, but if you want to emulate arcade games with MAME (Multiple Arcade Machine Emulator), you can search the 'tubes. What I'm doing here is putting a computer in a pretty box.
Hardware Disclaimer 2: Many folks that build arcade cabinets have a purist view of how these things should be done. They will prefer original Arcade CRT monitors and more expensive, higher quality parts. I am more of a pragmatist. I also have no idea what I'm doing, so I've also got ignorance on my side.
There's been a huge amount of work done in the last few years to reconcile the dozens of emulators and systems and the nightmare of keybindings, menus, and configuration. My first MAME machine was a few hours to install and literally weeks of messing around with the settings of various emulators. I started with the legendary v1 "X-Arcade Tankstick" that had was effectively a PS2 keyboard. I took it apart and built it into my MAME system's control panel. I then needed to tell each individual emulator the key codes for up, down, left, right, a, b, x, y, etc. Each emulator had a different configuration file. Some were INI files, some XML, some freaking magic.
It's a lot to ask in 2017 to dedicate a complete PC to a retroarcade - in fact, it's just not necessary. A $35 Raspberry Pi 3 (or even an overclocked Raspberry Pi 2) has enough power to handle all but the most complex emulators.
We also picked up a Hyperkin Retron console. This is a great legal way to plan retro games because it requires actual cartridges. We buy our games at Retro Game Trader. If you are EVER near Portland you HAVE to stop and check it out. It's insane.
There's a old joke about building a retro arcade machines - Is it more fun to play retro arcade games, or is it more fun to build a retro arcade machine with a cool front-end where every keybinding works in every emulator but you never get around to playing games?
A RetroPie inside an X-Arcade Tankstick
There's a whole series of gotchas that took me a few weeks to work through when taking a Raspberry Pi, RetroPie software, and an X-Arcade and getting them to work well together.
THIS blog post is going to be a collection of all the stuff I wish I'd known BEFORE I started on this path. Even one of these tips would have saved me an hour, so the collection of them is days of googling, forum reading, and trial and error.
2amp+ powersupply with a 5 foot microUSB cable. Make sure your powersupply does at LEAST 2 amps. Less and your Raspberry Pi may not boot up with keyboards or mice attached.
Remember that the goal here is to be able to plug this into your TV while you're sitting near or on your couch. You might even want a longer cable.
Make sure the microUSB powersupply cable length matches your HMDI cable length. You're only as useful as the shortest cable between these two.
PS2 keyboard - Yes, PS2. I picked one up at Goodwill or a local Thrift Shop. You'll need this to program the X-Arcade Tankstick. You change its mode switch, press a button on the controller while simultaneously pressing a key on the PS2 keyboard. You'll repeat this until all your keys are set.
And finally, last but not least. An X-Arcade Stick. You can get them with or without a Trackball (which acts as an independent mouse and uses its own additional USB cable). As I mentioned, I'd long-been a fan of all X-Arcade products. Their stuff is legendarily reliable and built like, well, a tank. They're fantastic in that you can even get adapters for your X-Box, X-Box One, Wii, Dreamcast, whatever.
My brother recently found an X-Arcade stick at a local thrift story for $30 and grabbed it for me. I opened it up and noticed it was the PS2 version from years ago. Fear not - you should be aware that there is the PS2 X-Arcade that requires a PS2 keyboard be attached, and there's the newer USB version. Here's the epic part - and reason #564 why I love X-Gaming as a company - you can upgrade the electronics in your v1 X-Arcade stick with a simple board for $35. And I did just this. This kit takes any existing X-Arcade to the latest hardware and you're going to want the latest if you want your X-Arcade to work smoothly with RetroPie.
I took the back off the X-Arcade and threaded the HDMI cable and USB micro cable through the back holes. I 3D-printed a case (the yellow cage in the photo below) for the Raspberry Pi but really any case will do as long as wires aren't touching wires. There's an RS232 cable and the vestigial green PS2 male that you can tuck away in there. I used the remaining hole to keep the purple PS2 female connector handy as it'll be used for "programming" the keys for the X-Arcade.
Yes, it's janky, but all I had was electrical tape. Ideally I'd get a rubber gasket for the wires to keep the tension off the Raspberry Pi and make it more "kid safe."
Again, follow these videos. If you're a little technical it's pretty straightforward stuff. The general idea is this.
The Raspberry Pi uses the SD Card as its hard drive.
The X-Arcade is a keyboard and you'll have the PS2 keyboard temporarily plugged into it for setup.
The Raspberry Pi 3 is best not only because it's fast but it's also got built-in WiFi. If you use a Raspberry Pi 2, you'll need a Wifi adapter.
With your computer, you will use Win32DiskImager to copy a pre-made image of RetroPie to the SD Card.
You'll put the SD Card into the Pi, connect the X-Arcade via USB to the Pi, connect the PS2 keyboard to the X-Arcade , connect the Pi's HDMI to a monitor or TV, connect the power, and boot up.
You'll follow some on-screen prompts (again, see the videos) and setup RetroPi.
Debugging often consists of using putty and/or Bash for Windows to ssh into the Raspberry Pi. The user name is pi and the password is raspberry so that's usually "ssh pi@retropie" then the password.
Little Gotchas when Hooking up RetroPie and an X-Arcade
Now to the little details that took me weeks that will hopefully help you.
Xarcade2Jstick vs standard keyboard mapping - Some people swear that the X-Arcade stick will/can get detected as a joystick using a user-space driver called Xarcade2Jstick. This driver is built into Retropie now and it takes your keyboard/xarcade and "lies" to the system and makes it look like two gamepads. Some folks swear by it. I fought with it for a week and decided that since I understand keyboards, I would just stick with keyboard mapping. Your mileage may vary, but the good thing to know (and try) is that if your system "just works" when you boot up, then perhaps Xarcade2jstick worked amazingly for you and you can skip a LOT of this mess. Sound off in the comments. The gent who made the videos also believes that keyboard mapping is more reliable and recommends this "non-standard" set up and programs it in "bank 2" of the X-Arcade. That means the toggle switch is in the second position inward, away from the serial point when you program it. He recommends this layout and I've used it also. This is a screenshot from his video.
NOTE: I needed to go into optional components in RetroPie setup and specifically disable xarcade2jstick. You can re-run RetroPie-setup from the command line as often as you like.
cd RetroPie-Setup
sudo ./retropie_setup.sh
Keyboard Bindings for RetroArch compliant emulatiors - Now, I think I understand this, but if I get it wrong, let me know in the comments. There is an organization called "libRetro" that comprises the libRetro library, the RetroArch frontend that runs libRetro programms, and Lakka, a Linux that's meant for retroarcades. You don't need to sweat Lakka as you used a default RetroPie image. But RetroArch you'll be hearing a lot about. Remember earlier when I was complaining about all the trouble configuring emulators? RetroArch has scoped, nested config files (with includes) that allow you specify your config and keyboard/gamepad/joystick mapping once and then participating emulators will "just work." Another way to look at it is this. In the past you needed lots of emulator programs from lots of people with lots of config that was all different. Retroarch tries to unify all of this so there's "cores" for each emulated system that Retorarch calls out to for the emulation. Follow the videos, but you'll basically go to /opt/retropie/configs/all and edit retroarch.cfg to support the keymapping above. MOST of the emulators will pick these settings up. But not all. More on that in a second.
Like this:
input_player1_a = t input_player1_b = r input_player1_y = q input_player1_x = w input_player1_start = num1 input_player1_select = num5 input_player1_l = e input_player1_r = y input_player1_left = left input_player1_right = right input_player1_up = up input_player1_down = down input_player1_l2 = u input_player1_r2 = i input_player1_l3 = nul input_player1_r3 = nul
input_player2_a = j input_player2_b = h input_player2_y = d input_player2_x = f input_player2_start = num2 input_player2_select = num6 input_player2_l = g input_player2_r = k input_player2_left = a input_player2_right = s input_player2_up = o input_player2_down = p input_player2_l2 = l input_player2_r2 = z input_player2_l3 = nul input_player2_r3 = nul
Exiting Games with the Xarcade controller - One of the most common questions I saw in the forums was "I can move around in the menus and launch and emulator but I can't exit it!" Folks were forced to pull the plug and hard reboot which isn't a sustainable solution. The xarcade has a "flipper" (imagine a pinball flipper's controlling button position) button on each side. The standard hotkey for exiting an emulator has historically been pressing the Player 1 start button PLUS the left flipper button. That's the 1 and 5 keys together if you look at the diagram above. You'll want to go to /opt/retropie/configs/all and edit retroarch.cfg and confirm that you have these lines somewhere: input_enable_hotkey = num1 input_exit_emulator = num5 Then launch emulationstation (or reboot), launch an emulator, and press P1 and left bumper/flipper. You'll also come to know the left and right flipper buttons as the virtual "insert coin" buttons for Player 1 (P1) and Player 2 (P2) respectively.
Some emulators don't listen to RetroArch settings - Depending on the RetroPie image you downloaded, you may find that some emulators don't listen or respect your core retroarch.cfg settings. Or, perhaps the defaults buttons don't feel right. For example, Sega controller buttons are two rows of three buttons each. You can override your settings to make your xarcade more intuitive. Go to /opt/retropie/configs/megadrive and edit the retroarch.cfg in there. Note that it includes the MAIN "all" retroarch so you're just overriding some settings on an emulator by emulator basis.
# Settings made here will only override settings in the global retroarch.cfg if placed above the #include line
input_player1_a = y input_player1_b = t input_player1_y = r input_player1_x = w input_player1_l = q input_player1_r = e
input_player2_a = k input_player2_b = j input_player2_y = h input_player2_x = f input_player2_l = d input_player2_r = g
MAME isn't working at all with the Xarcade - This hit me and I see lots of folks struggling. If the MAME core/emulator you're using doesn't integrate with RetroArch, you may need to manually keymap within MAME itself. Use the attached keyboard (while it's still attached) and when inside MAME press Tab. You'll go into the "Input (general) and go down the line one at a time and remap the keys. It's NOT obvious that you have to press and hold the buttons on your XArcade before MAME will pick up the new mapping. It's also not obvious that if you press AGAIN and hold that you can tell MAME another alternate key. In other words, the "OR" key. As in "1 OR 5" if you like. You might like to know that mame-advmame stores these configurations in /opt/retropie/configs/mame-advmame in *.rc files. For example, I had advmame-0.94.0.rc and wanted to be able to exit MAME from my xarcade. If I had a keyboard attached, I'd press "ESC" but with the Xarcade I wanted "Player 1 plus Left Flipper" to work. Then I wanted either "Enter" to confirm, or the main button for Player 1. I ended up with this. Again, this is for non-RetroArch advmame, but it makes the larger point in case you run into these kinds of emulators.
input_map[ui_pause] keyboard[0,enter] or keyboard[0,tab] keyboard[0,up] input_map[ui_select] keyboard[0,enter] or keyboard[0,q] input_map[ui_cancel] keyboard[0,5] keyboard[0,1] or keyboard[0,esc]
That pretty much covers all the hairpullingout of the last few weeks. The result is very nice though. I hope you make one also!
Sponsor: Check out Seq: simple centralized logging, on your infrastructure, with great support for ASP.NET Core and Serilog. Download version 4.0.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
.NET and .NET Core (and Windows!) have been getting better and better with Docker. I run Docker for Windows as it supports both Linux Containers and Windows Containers. They have both a Stable and Edge channel. The Edge (Beta) channel is regularly updated and, as a rule, gets better and better in the year I've been running it.
As a slightly unrelated side note, I'm also running Docker on my Synology NAS with a number of containers, as well as .NET Core (my Nas is an Intel chip), Minecraft Server, Plex Server, and CrashPlan.
NOTE: Docker for Windows requires 64bit Windows 10 Pro and Microsoft Hyper-V. Please see What to know before you install for a full list of prerequisites.
They publish their Docker images in a few different repositories on Docker Hub. It’s important to segment images so that they are easier to find, both on the Docker Hub website as well as with the docker search command.
microsoft/dotnet — .NET Core Runtime and SDK images for Linux and Nano Server.
The samples are super easy to try out - STOP READING AND TRY THIS NOW. ;)
I'm always impressed with a nice asynchronous ASCII Progress bar. I'm easy to impress. This is a "hello world" sample with a surprise ASCII art. I won't spoil for you.
All the images are managed and maintained on GitHub so you can get involved if you're not digging the images or files.
One interesting thing to point out is the difference between dev images and production images, as well as images you'd use in CI/CD (Build Server) situations to build other images. Here are some examples from GitHub:
Development
dotnetapp-dev - This sample is good for development and building since it relies on the .NET Core SDK image. It performs dotnet commands on your behalf, reducing the time it takes to create Docker images (assuming you make changes and then test them in a container, iteratively).
Production
dotnetapp-prod - This sample is good for production since it relies on the .NET Core Runtime image, not the larger .NET Core SDK image. Most apps only need the runtime, reducing the size of your application image.
dotnetapp-selfcontained - This sample is also good for production scenarios since it relies on an operating system image (without .NET Core). Self-contained .NET Core apps include .NET Core as part of the app and not as a centrally installed component in a base image.
dotnetapp-current - This sample demonstrates how to configure an application to use the .NET Core 1.1 image. Both the .csproj and the Dockerfile have been updated to depend on .NET Core 1.1. This sample is the same as dotnetapp-prod with the exception of relying on a later .NET Core version.
aspnetapp - This samples demonstrates a Dockerized ASP.NET Core Web App
Some of you may have .NET Framework apps running in Virtual Machines that you'd love to get moved over to a container infrastructure. There's a tool called Image2Docker that Docker maintains that might help. It helps migrate VMs to Containers. Check out the Image2Docker DockerCon talk or read Docker’s Convert ASP.NET Web Servers To Docker with ImageDocker to learn more.
Sponsor: Check out Seq: simple centralized logging, on your infrastructure, with great support for ASP.NET Core and Serilog. Download version 4.0.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.