 Welcome back to migrating a .NET Framework WPF app to .NET Core 3. In this second video, we're going to actually start the migration now that we've done the preparatory work. We're going to create a new CS Proj, make sure that we have updated versions of our NuGet packages, so that we'll be all set up for a video 3 where we actually start making code changes. So again, I see migration as a four-step process where you sort of prepare, you get the project file set up and adjust NuGet packages and other third-party dependency references, then a fourth step where you fix the code and then you run and you test and you find any runtime differences and you account for those. So we're on step two now. Now, one of the first things we have to think about when we're setting up our new CS project file is where does this project file live? That might not seem on the surface like a very interesting decision, but it actually is because it's going to, no matter what answer we give to that question, we're going to have some challenges. Now, the first option and the one that I would recommend starting maybe six months from now or whatever .NET Core 3 is in a state that you can go live on it, would be to just replace the old project file. You could imagine getting rid of the old project file, putting a new one in its place, and if you want to target both .NET Framework and .NET Core, you can use multi-targeting to do that. Right now, that's not a great option because multi-targeting doesn't work well with the designer. So if you need to go in and use the WPF designer to shift some UI elements or drop something in, you're not going to get to do that with this new project, or at least it may not always work well. Multi-targeting allows it to work occasionally, but you can't count on it, so you'll just be doing your UI updates in XAML. The whole multi-targeting process, I think, is the way we're going to want to do this eventually, but I don't think that experience is there yet in the .NET Core 3 previews. So if we don't do that yet, then we're going to have two project files, assuming that we want to continue building for .NET Framework, since that's the thing that we can go live on now and that has the designer support. So we either can put the C-sharp project files next to each other in the same directory, or we put them in separate directories. If we put them next to each other in the same directory, that's going to make it easy to reference all the source and the XAML and the resources, because they're all going to be in the same places relatively. But that's going to introduce a challenge because these two C-sharp project files are going to have the same default intermediate output and the same bin folders. So they're going to get in each other's way when they're restoring packages, when they're building. So you're going to have to make some changes to actually have them use separate output folders. And unfortunately, there's actually a couple issues right now with publishing a .NET Core app when you've changed the intermediate output folder, at least a .NET Core WPF app, such that you need to clean, you do a .NET clean prior to running .NET Publish. Totally something you can work around, but there's just some rough edges here and it's going to be a little bit of a hassle. Now again, this is a perfectly good option, but we're going to have to do a little bit of work to make it do what we want as far as just updating these output paths. So you might think, okay, well, I'll avoid that by putting these in separate directories. So that's going to solve all the problems I just talked about, but now you're going to have a problem. The new .NET Core project file format doesn't need to explicitly depend on C-sharp source, XAML, pages, or Rezex files that are in its directory or in directories underneath its directory. And if you're in a separate folder with your .CS branch, you don't get that benefit. You're going to have to explicitly reference all those things worse, because just adding those references isn't so bad. That's just like we used to do it with the old project file format. Worse, there's currently some issues I can go out and show you this GitHub issue, where right now you have to explicitly link those files. The automatic link generation isn't working. So in order for some XAML build processes, you actually need to add a link element to your pages so that they show up in the right relative path from your project files point of view. So you might say, I'm going to reference . . slash old project slash main window .XAML. But you also need to add a link element to that, saying that we'd link it to just main window .XAML so that it doesn't see that directory traversal because that will mess up some of the WPF build steps. So again, that's totally solvable, not blocking at all. It just means if we go this route, there's a few extra steps we have to take. So eventually, a year from now, six months from now, whatever, we're just going to replace the old project file with a new one that multi-targets. Everything will be great. In the interim, we have to decide between these other two options, both of which have a couple of rough edges, but shouldn't be blocking. So just heads up about that. So for this demo, let's go ahead and create a new project and we're going to actually use the in the same directory approach because I know there have been some other videos recently where people put them in separate directories. And so just for variety's sake, let's see what this path looks like and we'll go from there. So here we are in Visual Studio. So we need to create a new .NET Core project. This could just be right click, add new project. But again, I want to put it in the same folder and I don't want like the program.cs that gets auto-generated, all that stuff. So I'm actually just going to create the csproj directly. And rather than create it by hand, which would be one option, I'm going to go to a temporary directory and I'm going to say .NET new WPF. This way, I get the template and I don't have to remember what the SDK is called and stuff like that because you can see here's the contents of this auto-generated csproj file. It's got the nice Windows desktop SDK. It's got .NET Core app 3.0. It's the target framework. WinX, the output uses WPF True. This is what we want our project file to look like initially. So I'm going to come into VS Code, add a file. I'm going to call it beantraderclientcore.core.csproj because I can't call it beantraderclient.csproj since that would conflict. And I'm just going to paste this in. All right, there we go. We've got a csproj file. Now, for a simple app, maybe a Hello World or something a little bit more complicated, we would be done because if I come over into Visual Studio and I add that project to my solution, what you're going to see, let's see, come in here and add it, you'll see that we already have all of the C-sharp sources referenced. My Resx files are here. We've got our XAML in the views folder because a lot of that stuff is automatically included by the new project file format. It automatically looks for those and includes them in the right way in the project. In a more complex project like this one, though, we're going to want to go through and actually look at the old csproj to see if there's anything else we have to change because there will be some things that will be a little bit different here that we want to make sure are done right in the new project file. So what I'm going to do is I'm going to come over here to VS Code. I'm going to open both the old and the new project file. I'm going to put them side by side and let's go ahead and look through the old project file to see which parts of it we need to bring over into the new project file. Okay, so let's go through and see which of these properties and items we need in our new csproj. So we've got these imports. We don't need this because we reference an SDK and an SDK attribute on the project will imply that we're importing props and targets that are necessary to build this type of a project. So that takes care of sort of the standard imports. So we skip over that. We do probably want root namespace and assembly name because if we add new files, we want them to use that namespace by default and we want the app to build to be called BeanTraderClient. So it looks exactly like the old one, not BeanTraderClientCore despite the different csproj name. We don't need to auto generate binding redirects because .NET Core doesn't use binding redirects. I don't use these constants in my project, but this reminds me that I do probably want to add a constant because I find it's useful to define a constant indicating that we're building for .NET Core so that if we have sources shared between the .NET Framework and .NET Core projects, in some cases we may need to do one thing for .NET Core, one thing for .NET Framework if there's small API differences or something. So having this constant available makes it easy to use a pound if to do that. There's application icon, we need that. So we'll bring our app icon over and here's the things that we're building. Most of these we won't need like the application definition being including app.xaml, that's done by default. All C sharp files in or under this directory are compiled by default so we skip those. XAML pages are included by default so we skip those. Here's a resource, embedded resources are included but resources are not so we need an item group where we can add this resource. We also have to add content typically. Well, I mean some things will be added by default as content but this one won't, this one's interesting because look it's a XAML file but I'm adding it as content and the reason I'm doing this is because I'm using my apps theming to change like the color scheme or the accent of my app dynamically and customers could choose which theme they want but I'm actually loading some of the themes from disk so that we can have a style defined in XAML on disk and then at runtime we load that dynamically and we use it as a theme. So that means that this XAML file does not need to be a page but it should be content so I'm actually going to copy it as content because actually if I come over and look in Visual Studio you will see that XAML page is right now included as a page because that's what happens by default so instead we're going to add it as content and I'm actually going to remove it as a page and I'm not only going to remove default accent.XAML I'm going to remove, I'm going to use a globbing pattern like you can with the new project files. I'm going to remove that file in any folder not just the resources themes default so that way after we copy it to our output directory or to an intermediate output directory we won't start building it as a XAML page from there either. These ones are fine. Assembly info.cs is an interesting one. It's included automatically so that's good but if we look at what assembly info.cs is it has a bunch of assembly attributes and this was part of our new project template when we created the WPF app originally on .NET Framework and it has these attributes for things like assembly title, copyright culture and so on and these assembly level attributes are auto-generated in .NET Core based on properties in your project file so we actually can run into an issue here because these attributes will conflict with the auto-generated ones. Now if this was a new project it wouldn't be a problem because we wouldn't have assembly info.cs we would just set properties in our csproj to define those values but in this case it does become a problem so I'm going to add a property called generate assembly info and I will change that to false instead of its default true and what that means is that we're not going to auto-generate those assembly level attributes and therefore we'll just use this one instead. Other things that might be interesting the app config is included automatically embedded resources are included automatically. Resources are not like I said if we come over here and look we can take a look at the images and these images are build type none so they're in the none group and in fact I want them to be resources so that they're embedded in my assembly so I need to add more resources here but again we can use that globbing pattern so instead of adding each image individually I can add all PNG files anywhere under the directory the csproj or if I want to say just under resources or resource images you could scope it but I'm going to include all the PNG files as resources. Finally, remember I said in the last video that by switching our new get dependencies to use package reference syntax instead of using a packages.config file that would make things easier later well here's what it makes easier it means that I can copy and just paste that item group and this is going to work in this csproj the same as it the same as it would have worked previously so we don't need to make any changes here we just pick up our new get references we plop them down here and we are good to go so at this point the csproj file is essentially done the only thing that's left to be done is to update the new get packages to the right versions or to change them if we need to change them so I can come up to my command prompt here and do a .NET restore and I have to specify which projects since I have two csproj files here now and I can do this from Visual Studio as well there's a lot of stuff that can be done either from the Visual Studio IDE or from the command prompt both are great it's just a matter of preference so all sort of bounce back and forth so you can see both ways for a lot of the operations that I'm doing in this case I did a .NET restore I get some warnings that there are packages that are targeting .NET framework that I'm using instead of .NET Core and remember we talked about this previously that's expected this is the point where I'm going to need to update some of those so there's different ways we can update them one way is to do a .NET add and then I specify the package that I'm adding to and I then say package and I need to give the name of the package so I'll say maapps.metro and this will update the maapps reference to actually it'll update it to the latest stable version and in our case we don't want the stable version we want the one we found out on on NuGet that supported .NET Core so I will search for maapps.metro it's this 2.0 alpha that we want so I'll actually copy that version so I get the version right we will add that and so by doing a .NET add package I'm now updating the package version that we're depending on to a more recent one which supports .NET Core if we come over to Visual Studio we can do the same thing from here if we go to Manage NuGet Packages and see the ones that are installed so we can take things like the Microsoft Azure Common I know it's the 2.0 version did not support .NET standard or .NET Core but the latest stable one does support that so we're going to update say yes we'll let that update and then you can see here some of the other warnings there's Microsoft Identity Model Clients Active Directory did not target .NET Core but the newer version does so I update that one to 4.5.1 instead of version 2.29 and at this point oh and then the NITO Async is another one that has a pre-release that supports .NET Core so I'm going to update from 4.0.1 to 5.0.0 pre-05 and that should be all of my packages that need to be updated and again in the first step we went through and sort of understood what our packages were so that we knew if we were going to have any issues so we sort of know now what needs updated and we can do those updates pretty quickly let's do one more .NET Restore I have to save changes when I make changes with the NuGet Package Manager here it doesn't actually save the changes until I hit that save button so now I'll do a .NET Restore and I still have one warning there's this Microsoft XAML Behaviors WPF so what is that? I'm not depending on that strictly it must be a transitive dependency that comes in thanks to the closure of dependencies of things that I depend on at a top level an easy way to find out how things are being pulled in is to go look in your object folder there should be a file called project.assets.json this is produced when you do a .NET Restore and it shows everything that's pulled in from NuGet the libraries, the files which packages they're part of why those packages are referenced so I can search for that Microsoft XAML Behaviors I see it is included because it's a dependency of the Controls EX package Controls EX in turn is included because it's a dependency of MAAP's Metro okay so this is interesting my project is depending on a NuGet package that targets .NET Framework instead of .NET Core you remember I said that's not really what you want it's okay but it's not best in this case there's not a lot I can do about it because it's not a direct dependency if I really wanted to use a different version of this Microsoft XAML Behaviors WPF library I could add a reference to a particular version of the NuGet package as a top level dependency and then everything would use that but in this case I don't think there even is a newer version that's the latest version so there's nothing to switch to but because it's not a top level dependency it's more likely to be okay MAAP's Metro with their version 2.0 has said this targets .NET Core so they have a dependency which depends on .NET Framework but presumably when they targeted .NET Core they tested on that platform and they're saying yeah this works on .NET Core it's safe to use so I'm gonna trust the owners of the packages I'm depending on directly and say if they're pulling in something transitively that targets .NET Framework it's probably fine because again many .NET Framework packages can be used and this one probably is safe at least in the ways that MAAP's Metro and Controls EX are using it otherwise they would have trouble targeting .NET Core so this particular warning is probably safe and we can consider our project file done at this point it looks a lot like our old project file but way smaller we automatically include a bunch of stuff we make a few modifications with globbing patterns and we've got our references to other packages or projects and that's really all you need to do and now we have two project files one that targets .NET Framework one that targets .NET Core next up we're gonna do a .NET Build and we're gonna start going through Build Errors and that's gonna be now that's the majority of the work in a migration effort so that's probably gonna be two videos so I think coming up in videos three and four we're going to be doing the code level changes that we need to make this app work on .NET Core