 Welcome back. Let's continue fixing build issues to get our bean trader sample working on .NET Core. You remember during the last video we started going through these build issues and we fixed all of the errors coming from the first pass of the C-Sharp compiler. So in this video we're going to fix the remaining issues and fix everything so that the second pass succeeds and we can cleanly build for .NET Core. So here's our 11 errors that were remaining, not too many. Hop over into Visual Studio and start walking through these. The first category of error we have is with Castle Windsor APIs. Here we are trying to use installers from the current assembly and you see that from assembly.this for finding the location where the installers are coming from. It says .this is not available for beantraderclient.core but it is available for bean trader client. Now remember we didn't change the version of Castle Windsor we're using. This is the Castle Windsor 4.1.1 being used in the .NET Core and in the .NET Framework projects. So what this means is that the different binaries for .NET Core and .NET Framework must have slightly different surface areas for Castle Windsor. This is not uncommon especially around some of these reflection code paths that look at the current assembly. And it just reflects some of the different APIs that the .NET Framework exposes that then change what Castle Windsor is able to do. So it's the same NuGet package but there's different binaries for different .NET targets. There could be small differences like this. Typically in these sorts of cases though there are easy workarounds by just using a different API. So in this case instead of calling this to get the current assembly. We can say from assembly containing and pass in a type like the current type that we're in. And it will look for installers in the assembly that contains Bootstrapper which of course will work out to be exactly the same as the assembly.this. But this API works both for .NET Core and .NET Framework so that's the way we want to go. Similarly in the installers themselves when we're looking for classes to register we can't call classes.from this assembly. Because that doesn't exist for Core though it does exist for Framework in Castle Windsor. Instead we can say from assembly containing and we can use the same sort of pattern. Where we just give a type in the assembly that we care about and it finds it that way. So that's that fixes that one and you can hop over. Now you do notice that as you're working through these visual studio allows you to look at this source that's shared between the two projects. From the perspective of either the .NET Framework project where this is fine or the .NET Core project where it's problematic. So depending on which target you're working on you can change that view which is sort of convenient. But again we're going to change this to from assembly containing type of view model installer. Okay and the Castle Windsor stuff should be good to go. Other things there are a lot of issues in this app.xaml so let's take a look and I'm going to collapse that. So a lot of these theme manager and accent related APIs appear to be missing. So if we take a look at theme manager we can see that yeah sure enough those APIs are not here. But if we look at this from the .NET Framework point of view all these APIs are okay. And here if we look at theme manager they're there and in fact we see these two theme manager APIs look fairly different. So now this is something that I talked about earlier. This is a case where we were using Moab's Metro 1.6.5. We upgraded to 2.0 so that we could in the .NET Core project because the version 2 of Moab's Metro actually targets .NET Core 3. But we didn't upgrade in the .NET Framework project so we never really tested out to see if there were any breaking changes in this major version change of Moab's Metro. And it turns out there are. You can go online and search and you'll find that there are in fact breaking changes in the way that themes and accents are handled in Moab's Metro 2. So we have a bit of a dilemma here because we had previously upgraded our Moab's Metro dependency from 1.6.5 to 2.0 in order to use a package that targeted .NET Core. But now we find that the API surface area is different in Moab's Metro 2. So we either need to roll back to 1.6.5 or we need to fix our app. Now in general I think the best practice here is to just update your application to use the newer version. Remember in our very first video I said one of the things you can do to prepare for a .NET Core migration is to upgrade your NuGet packages so that you're using up to date versions, especially if older versions don't support .NET Standard or .NET Core. So if we had done that we would have made the necessary changes to our app to support Moab's Metro 2 at that point. And this wouldn't be a problem. In our case we just went ahead because I'm doing this quickly. And so now we have a bit of a dilemma. If this were not a short video I'm recording I would probably just go in and change to use Moab's Metro 2. But in this case I'm not going to. And you may not want to also if you are in a scenario where you have a large dependency on a particular old version of a NuGet package and it's going to be a lot of work to change. In my case it wouldn't be that much work but this video is about upgrading to .NET Core 3. It's not about upgrading to Moab's Metro 2. The alternative of course is that we can continue to reference the old NuGet package because we can reference .NET Framework Assemblies. There's just a little bit of added risk that if those .NET Framework DLLs try to use an API that doesn't exist on .NET Core we'll get runtime errors. In this case though I think that the risk is fairly low both because our Moab's dependency is light. We're only using just a handful of APIs out of Moab's Metro. And because it's a UI library and I've noticed that as similar as .NET Framework and .NET Core surface areas are the surface areas for their WinForms and WPF stacks are even more similar. So a light dependency on a UI library it's probably safe to just continue using the older version of Moab's Metro so that we don't have to pay the cost of upgrading to the 2.0 surface area right now. Of course that's just going to be some technical debt so if you were to go this route because you didn't want to upgrade to a newer package version that's okay but you'd want to track somewhere that there's a work item that in the future you're going to need to make that upgrade eventually. Also when you do it this way again you're going to want to be sure to thoroughly test those code paths to make sure that everything continues to work on the old version. Okay so we've made the change and now if I rebuild the solution we should have less errors. Okay in fact we're down to just a single error but we do have some new warnings. You see that we get warnings about Moab's Metro 165 being restored using a .NET Framework target instead of .NET Core one. Of course this is expected that's what we knew would happen and we've decided we're okay with that which means we don't have to change how we're using the API and we'll test this out later. But at this point we've only got a single error left and it has to do with our WCF client. So newclient.open does not exist on .NET Core. If you look at this new client it is an instance of our bean trader service client which if we look at the implementation here this was auto generated by ServiceUtel which is our WCF client which was auto generated by ServiceUtel. So this almost works on .NET Core but it doesn't quite because there are some differences in WCF client APIs between .NET Framework and .NET Core. The largest differences are that not all of the same bindings are available. Most bindings are available but WS bindings are available. WS bindings are not available on .NET Core. Pipe binding is not available on .NET Core and there's a smaller set of security. You can't do message level security on .NET Core. So there are some differences there. The other large difference that you're almost certainly going to notice is that .NET Core does not use configuration to set up its WCF clients. So we don't use app config to configure our clients. Instead you have to do it in code. Of course this WCF client that was generated by ServiceUtel when we generated it it gave us app config to use and the client code assumes that it's going to be loading configuration from the config file. So this is not going to work anymore. What you need to do if you're migrating from .NET Framework to .NET Core using a WCF client you need to regenerate the client but we have tooling to do that. There's actually two different ways that you can approach that. One way is you can do it directly from Visual Studio using, let me bring this over here so you can see, using their WCF Web Service Reference Provider tool which makes it very easy to generate a WCF client right from Visual Studio. Alternatively we have, if you like the command line nature of ServiceUtel there is a .NET ServiceUtel tool which is a .NET CLI tool that is similar to ServiceUtel but will generate WCF clients that are .NET standard compatible. So you can use them from .NET Core or .NET Framework or other platforms and that will work as well. So feel free to go check out either of these tools either .NET ServiceUtel for command line option or the connected service path using Visual Studio. Both are good. In this case I'm going to use it, I'm going to do it through Visual Studio because I have to know that .NET ServiceUtel doesn't work well when you have two project files in the same folder. So if I wanted to use .NET ServiceUtel I'd actually have to like copy my project file someplace else, run it there, copy the client back over. It'd be a little bit of a hassle. So instead what I'm going to do is in Visual Studio I can right click on the project and I go to add and we'll say add connected service. In here we choose WCF web service reference provider and this is how we're going to add our WCF client through Visual Studio. So we have to paste the URL of the service that we're using. We'll say go. We'll give it a namespace that makes sense like being trader.service and we've got some options which are fine and we'll click finish. So this is now going to generate a .NET standard compatible WCF client for us that we can use in place of the old ServiceUtel generated one. So it's generating it. Something that we're going to see is that this, okay it's going to give us a little website that tells us about the whole connected service experience. What you're going to find though is that we now have this extra folder here under connected services called being trader service and in it we have reference.cs and here is our .NET standard WCF client. You're going to find it's very similar to the one that was generated for .NET framework use but it's not exactly the same. In fact if I take a look at our previous client some of the differences you'll notice are that namespaces are different. In the old one I had my models in a being trader.models namespace and the services themselves weren't in a namespace at all which probably was incorrect but I was making this sample quickly. Here, on the other hand, everything is in a namespace called being trader.service. So I can remove being trader from my .NET core app and just use the new client but I'm going to have to make some changes to the code to reflect the fact that the API is slightly different and that the namespaces have changed. But there's a design decision to make here. I now have two WCF clients one of which is going to work on .NET core. Both of them can be used from .NET framework. So I have to decide am I going to change the code so that it always uses this new .NET standard client or am I going to change the code so that when I build for .NET framework it uses the old client and when I build for .NET core it uses the new one. Both have pros and cons. They're a similar amount of work in my opinion. What you want to base this on is whether you need your existing .NET framework project to stay exactly as it is or if you're okay making some changes to it. If you need the advantage of leaving the .NET framework project targeting the old client is that you know that code works. You've been using it potentially for a long time and you don't want to churn a stable product. But the downside is that now you're going to have different code paths where you're calling your WCF client. You're going to do it one way compiling for framework, one way compiling for core. You're going to have both of these clients checked in and your code is going to start to bifurcate. So if possible I think it's better to actually just update both projects to use this new client. That way you just have everything using the same code paths. You can make it work the same everywhere and it's a little bit simpler at the end of the day. So that's the way I'm going to go in this demo. I understand in the real world you may not want to make large changes like swapping out your WCF clients in your existing .NET framework project and so it's okay to use like a pound if to say this is the way we do it on framework, this is the way we do it on core and we have two separate clients. For this case though, let's go ahead and remove bean trader.cs because we're not going to be using that anymore. And instead we're going to add an existing item to our .NET framework project. We're going to add this reference.cs that was generated under connected services making sure to add it as a link so it's one shared source file. And now we're going to have both of our projects using a new WCF client that is compatible with .NET standard. Now if I rebuild I'm going to have some more errors because remember this WCF client is a slightly different shape. The main thing I'm going to have to change here is I just need to update a bunch of namespaces. See this was expecting things to be in, to not be in a namespace. Now they're in the bean trader.service namespace so I'm going to fix those. And all of these are going to be similar. I need to fix up namespaces across a few different C sharp files as well as in XAML. So this is kind of boring. So I'm going to pause the video for a couple of minutes while I go through and fix these up and then I'll be back as soon as I finish fixing these and we will move on. Okay I'm back and we're getting close now. At this point we've only got two errors left since I fixed all the namespace references. One of them is interesting it's that one of the differences in the WCF clients is that the constructor for our bean trader service client has a slightly different shape. Previously we were specifying the callback handler we wanted to use and if we look at this we don't have a public constructor that takes an instance context or callback handler. Now we do have a base constructor that takes that. So what we can do is since this is a partial class and we know we want a constructor of a particular shape that doesn't exist, we can just add a model that extends the bean trader service client. So in my .NET Framework project since we want this to be present in both of them I'm going to add a new class I'm going to call it bean trader service client and I will fix the namespace to match the other one this will be a public partial class and I just need to make a constructor for this thing that is able to call the base constructor in fact this one right here it takes an endpoint configuration and a instance context looks like what we want so let's take a look here this is good I'll just copy this signature we'll call base callback instance endpoint configuration let's put this down here for readability's sake okay so now we should come back into our factory and we should be able to specify instance context and the endpoint that we want to use now note that we do need to pass this extra argument the endpoint configuration because remember this isn't picked up from app config anymore it has to be specified programmatically and if we look at our auto generated client you can see that it picked up from the services definition the server side definition of the WCF service what this endpoint should look like it has the binding being configured here our net TCP binding it also will have the default endpoint that was specified by the service and this is the stuff that previously would have been put in an app config but now it's put right here in code in the client and so we can just specify that we want to use that configuration by using this enum value and this should work so we'll go ahead and rebuild again and at this point we only have one left it says that open does not exist and of course this is not a surprise because remember we saw that the open API didn't exist in the first video when we ran the portability analyzer now open is available for dotnet framework but if we're going to be running on dotnet core as well we have to use open async now in this case fortunately that's an easy change because we're running inside of an async method anyhow so it's easy to drop in await new client on open async and that will work if we had decided to have separate clients for dotnet framework and dotnet core the old WCF client for the framework one and the new one for core this would be a place where we might do if, net core something like that and then say you know else we use the open API so this is a place where we could have potentially had different code paths for dotnet framework and dotnet core to call different open APIs on our WCF client in this case we decided to use the same client for both so that's not necessary and so we will build one more time and we find no errors let's come back over into our command prompt we'll try it from here do a dotnet build of our core project and oh we got some transient WPF stuff just because I have visual studio open at the same time which normally you wouldn't if we rebuild this there you go zero errors so we have successfully built the bean trader sample for dotnet core 3 and it's ready to go in the last video we're going to actually run it and make sure that we have tested it to ensure that everything works the same at run time as we expect it to