 Hello! Today I'm going to be porting a .NET Framework WPF app to .NET Core 3. Now this video will be a little longer than normal for me because I want to show the entire porting process start to finish. So I'm actually going to split it up and what you're watching now will be the first part of a five video series in which we do the end-to-end migration of a WPF application to .NET Core. We recently had a blog post and Channel 9 video where one of our .NET PMs, Olia, ported a simple WinForms app to .NET Core. So this is going to be kind of similar to that. Some of the techniques will be the same. But I wanted to do this video also because by splitting it up and spending an hour or two on it I think we can see a more complex example and this way we get to see a WPF app as opposed to the WinForms one which Olia ported. So the migration process that we're going to go through during these videos is four steps. The first step which we're covering in this video is is all about getting ready to port. It's about understanding the dependencies the project has so that we know what work we have ahead of us and getting the existing .NET framework project into a state that will make it easy to port in the subsequent steps. The second step is actually migrating the project file itself. .NET Core projects use the new SDK style CS project file format so you need to either create a new project file for your .NET Core port or you need to update the existing CS project file to use the SDK style. The third step is what people often think of when they think about porting to .NET Core which is making the code level fixes to get it building against the .NET Core target. So that would be you know API level differences that need addressed either because of changes in the .NET framework or in third-party packages you use because we're using WCF here we're going to have to regenerate our WCF client and so on. So it's all about those sort of code level fix up and this will actually be two videos. This will be videos three and four since it's the lion's share of the work. And then the final step is running and testing the application. People sometimes think that once it builds you're done but there are a number of differences between .NET framework and .NET Core that don't show up until runtime. So you really do need to make sure that you've tested the app, you've exercised its interesting code paths on .NET Core and make sure that it runs well. So that will be our fifth and final video. So the app that we're porting is you know like I said it's a step up from Hello World but it's still fairly simple it's not especially large but I wanted to make it interesting by using some dependencies that might be non-trivial to port and that are common in real world WPF applications. So this app is a commodity trading application I call it bean trader you trade imaginary beans with other users and it communicates with a backend service using WCF it has a duplex net TCP binding and so it's got that WCF dependency it also uses some third-party UI controls from my apps Metro uses dependency injection from Castle Windsor and a whole variety of .NET APIs that are common in WPF apps like getting settings from an app config file or the registry using a variety of resources and so on. The app is up on GitHub so you can go check it out if you want at github.com slash MJ Russo slash bean trader you will find the WPF app in the bean trader client folder bean trader server has that back in WCF service which you can just run locally I have it hosted up in Azure right now and so you can check this out for yourself I got some notes on how the migration should be done and actually if you take a look at the branches there's a net core branch which has the final state already ported to .NET Core and .NET framework so you can find you know the final ported product in the net core branch net effects and master right now are the same they have the initial state of the project and migration process is a branch where I'm going to commit after each of the videos I record so that you can see the state of the project as it progresses through the migration process. Also I do want to mention that this WPF app is not meant to be used as a WPS best practice sample or anything it's not a reference app for WPF that's both because I'm not a WPF expert and because I intentionally did some things in sort of roundabout ways in this application to make the porting a little bit more interesting this is all about the migration process from .NET framework to .NET Core not about showcasing the right ways to do things in WPF just a quick warning. So let me briefly demo this app for you and then we'll go ahead and port it and I'm not going to spend a long time on the demo because the app itself is not the interesting part it's the way we make it work on core but if we run it you see we've got this bean trader UI it's styled with my apps themes and accents I can log in and it shows me how many beans I have and it shows me trades that people have proposed. I will also start up a second instance of this app so that we can sort of see how in real time things are updated let's log in here as a different user maybe as Daniel and then here I can see okay Daniel will give me 20 red beans for 10 blue and 5 greens if I accept it you can see that both users are notified bean counts are updated and so on then maybe I can make a now I've got a lot of blue beans so maybe I want to give five blue beans and get I don't know five green beans and then that shows up for both users as well so that's the application nothing fancy but it's hopefully a little bit more real world than just you know saying hello on the screen because we're using a WCF client we're using app configuration we're using my ops metro dialogues and so on so let's go ahead and part this the first step like I said is that we want to prepare and understand the work that we have ahead of us and so we're going to look at our dependencies we're going to look at third party dependencies we're going to look at dot net dependencies for the third party once the first step if you have packages dot config file we're going to want to change this because the packages config file lists all of the new get packages that our project depends on in fact it lists the sort of transitive closure of all of the new get packages in dot net core using the new SDK style project we no longer use packages dot config instead we use the new newer package reference format to pull in new get dependencies so one of the things you're going to want to do to get your project ready to port so you're going to want to make that transition so right click on packages dot config and click migrate packages dot config to package reference if you haven't done this already with your project and this is going to do two things for us first it's going to migrate to the new package reference format so that we can just copy and paste our new get references from the old project into the new one and it'll make that that process super easy in the next video and it allows us to only reference top level projects instead of the whole you know transit of dependency tree so the migration tool in visual studio is really nice and identifies the top level projects and then we have an opportunity to select any other new get packages that are dependent on that would like to promote to top level dependencies in this case I don't want to make any of those top level and then we click OK it makes the changes it's going to remove our packages dot config file and will update the CS project file to use package reference instead so let this finish generates a little report showing what changed that's fine and let's go ahead will save the changes to the project file and then I'm actually going to open this up in visual studio codes that we can easily see the CS project file without having to download the project in visual studio and you can see that down at the bottom of the project file there's a new item group with these package reference elements and so this is the replacement for packages dot config and like I said one of the nice things about this format is that now I'm just looking at the top level packages so these are the packages that I need to have present for my project to work and that are going to need to work on dotnet core so at this point I can review these and make sure that I have a version that's going to work for me when I actually do the dotnet core migration so if I go out to newget.org we can start looking some of these up and see what our options are so we have Castle Windsor for example and we're using Castle Windsor version 4.1.1 so I'll click on that version and you can see dependencies that has dotnet framework dependencies and dotnet standard 1.6 dependencies so this package should work as is on dotnet core because dotnet core of course can depend on dotnet standard packages as well another view you can use instead of newget.org if it's hard for you to tell which dotnet targets are supported you go out to foogit.org it's the exact same URL but replace the N in newget with an F this is a site that some community members made that gives another view into newget packages it gives a little more details as far as what API's are present and it specifically lists frameworks up at the top here so we can see dotnet 4.5 and net standard 1.6 so this package is fine we can also look at say MAAPS.metro and we see that once it loads here MAAPS Metro version 2 at least supports dotnet framework and dotnet core 3.0 but we're using version 1.6.5 so if we go back to that we see ah here it doesn't support dotnet core it only supports dotnet framework this can be similar if I look up for example the Nido async or the Microsoft Azure Common libraries all of these support dotnet core or dotnet standard in a more recent version so here 221 supports net standard 1.4 but some of the older versions that my initial sample depended on don't support dotnet standard this is going to be common a lot of older WPF and WinForms applications will be using older versions of newget packages that don't support dotnet framework or I mean dotnet standard or dotnet core but they have newer versions that do so that's the second thing you can do to get ready to port you remember that I said you can get ready to port by migrating to the package reference format for your newget packages the other thing you can do is upgrade to newer versions so that you know when you go to dotnet core you'll be able to use the same newget packages you were using previously now sometimes that may take a little bit of work like if we make a major version change like for mobs metro 1 to 2 there could be breaking changes so in some cases you may not want to actually update because you don't want to make all of the changes to use this new new version but eventually that should be done and so this is a good time to take care of it if you're able to because it's going to make the migration a little bit easier now what if you don't find a an updated version that references dotnet standard or dotnet core or what if you really don't want to move because you don't want to take some change in surface area of newer versions of these packages it's possible to depend on dotnet framework libraries and newget packages from dotnet core applications and we allow that because the surface areas are so similar nowadays that those sorts of dependencies often work but they don't always work and see if you're going to depend on a dotnet framework package you need to be a little bit cautious about it you need to keep in mind that that's going to require some extra testing because what will happen is we'll allow it to build but at run time when you're running on dotnet core if your dotnet framework dll or newget package that you're depending on calls an api that doesn't exist on dotnet core that only exists on dotnet framework you're going to get a runtime error and so there's an extra test burden if you depend on older dotnet framework packages or libraries but we allow it because there are some situations where an old newget package hasn't been updated in years it would work fine on dotnet core it just hasn't been retargeted so in those cases we allow you to use those those libraries they work just make sure that you test that at runtime you're not going to get a missing method exception or something like that okay so we can go through these individually but i i know that they all either are supported on net center net core or have updated versions that are and i'm not going to update to the newer versions now i'll do that in the next video in the interest of keeping this first one short but that's reviewing your your third party dependencies the other thing we want to look at is first part you know dotnet dependencies like different apis we're calling from the dotnet framework to make sure that those same apis exist in the dotnet core surface area and for that we're going to use the dotnet core port of the dotnet portability analyzer which is a tool that the dotnet team created and maintains that will look at your binaries find all of the dotnet apis that are called and then produce a report showing whether those apis are available on different dotnet targets that you care about the tool works both as a visual studio plugin or from the command line now we've talked about this tool a lot in the past so if you're already familiar with it you can be done with this video move on to the next one because the next five or six minutes will be review but for folks who haven't used the tool before let me show you quickly how it works i like i said you can use it from visual studio or from the command line both work well i'm going to do it from the command line just because i feel like we demo that less often and i think it's a great option so if you're on api port you'll see there's a few different commands you can run list targets will show all of the dotnet targets that you can get information on list output formats will show the different output formats that we can use or run that quickly you can get output form output formatted as html excel or jason and then the the command that we really care about is analyze which is actually going to do the analysis of our project so we'll do api port analyze dash f give the path to are the binaries that we want analyzed dash r to specify which output formats i want i like to do both html and excel because i think they're both useful the html report in my opinion is the most human readable and the easiest to get an overall sense of what apis are present or missing the excel report is nice though because of course it's writable you can put notes in a new column so if you're reviewing this with a team or working through maybe migrating away from some apis that aren't available on dotnet on dotnet core you can use the excel spreadsheet to track that keep notes and so on and then we'll do dash t to specify the dotnet target that we want to use i'll say dotnet core and i don't i could specify which version of dotnet core but by default all of the targets will pick the latest version in this case that's dotnet core 3.0 so i run the tool it has produced this html file as well as the excel spreadsheet you see so let's pop this open see what's in here the top we have all of the binaries that were found in that path that i provided and how compatible they are with dotnet core and you can see these are fairly high numbers which is nice but something i want to emphasize is that you shouldn't look too much at this this number it doesn't mean a whole lot you may have a 85 or 90 percent here and that's okay because the apis that you're depending on are easily worked around or there are other alternatives that you can use instead you might have a 98 percent here and have a big problem because you're using some apis like creating app domains or remoting apis that simply aren't supported on dotnet core so now you have more work ahead of you this single number doesn't tell you a whole lot what you really need to look at is to drill into the eight the binaries that you own the source code for so in this case that's only this top one bean trader client and look at the apis that are missing which will be the ones with these red x's here in the dotnet core column make sure that for all of those you have an idea of how to work around them in this case the only apis that are missing from the bean trader client app are some wcf client base apis close and open are missing i'm not super worried about these because i know that wcf client apis are generally supported on dotnet core not all wcf client apis but um a good subsection and so certainly there are ways to open and close wcf clients there are probably alternative apis i can use here probably async alternatives to these synchronous ones that are no longer present so this makes me feel pretty good now we do have information on our other binaries but this is not interesting either because i don't own the source there's nothing i can do about these ones like castle winsor castle winsor is missing some system dot web apis that it was using if this was my code would have to migrate to using like some asp.net core alternatives and for the uh logical get data set data stuff i would use async locals but i don't own castle winsor and in fact remember we looked and we saw that castle winsor version 4.1.1 is targets dotnet framework and dotnet standard one six so because it targets dotnet standard one six i have confidence that there is a castle winsor binary in that new get package that's going to work for me this particular one that was in my binary output folder that targets dotnet framework well maybe it doesn't work but the castle winsor package supports dotnet standard so there's another binary that will be used that will work so this one doesn't even really matter so these these other libraries these other binaries you need to make sure that there are versions of these that work but we've already done that by looking through the new get package dependencies and other third party dependencies that our our project has and making sure that there are alternatives there that will work for dotnet core and so when we look at the api port report you really only need to look at things that you own and just look at these apis to make sure there's nothing really crucial here that's going to block you so at this point i feel pretty good about porting to dotnet core we've reviewed our new get package dependencies we've upgraded to use package reference format which will make the migration easier and we've looked at an api portability report to make sure that we understand which dotnet apis we're depending on may not be present once we migrate to dotnet core so that we know that those are things that we can work around this point we're ready to start the migration which we'll do in video two