Before we jump into the last installment, let's briefly review what we leaned in part 1 and part 2. If you're just jumping into this here, you probably want to go back to the beginning and read from there.
- Web apps are complex by nature
- Moving from desktop to web is also complex
- Web app development can require you to learn a bunch of new stuff, compared to Winforms apps
- WebMAP uses super cool rocket-powered tech to make it easy to move to the web
- WebMAP uses weaving so you can work on familiar code while the web complexity is hidden.
A few more words on weaving
Let me put this illustration back up here:
Ok, so about all that weaving. First of all, AOP isn't a new concept--it's been around for years, although possibly more familiar to Java developers than C# devs. Tools like Postsharp have made code injection for C# easier, but the Roslyn compiler was really the game changer. Roslyn made AOP easier because you could rewrite the code before compilation as part of the build--rather than having to massage the IL after the compiler was through with it. The other thing Roslyn had to do to make AOP simpler was to make sure debugging wasn't hosed--you want to debug the original "undecorated" code, not the rewritten code.
It's beyond the scope of this blog post to dissect the rewritten code--you can see it for yourself in the \obj folder. I can tell you our simple form1.cs file grows substantially when all the aspect code is injected. Sure that code could be in the original source files (before injection), but it would require the same code to be duplicated over and over again. For example, every object in the UI needs code to track whether or not it has changed (ie is it "dirty"?). All that duplicated code in our sources would violate the Don't Repeat Yourself (DRY) rule. Instead, injecting it via weaving into our pre-compile C# files keeps the user-facing source code clean and uncluttered, while still allowing for really functional code that gets built.
Looking at the front end
That basically covers the back-end, or server side, of the code. What about the client, or front end?
Our app gets a bunch of files that will be familiar to front-end web devs who use Angular but maybe unfamiliar to winforms developers. What's in the folder?
The droids you're looking for are in the \src folder. Let's take a look.
The time has come to switch from Visual Studio 2017 to Visual Studio Code. VS Code is the free, open-source IDE from Microsoft and right now it just works a little better on Angular apps. For one thing, it comes with a built-in Powershell terminal so you can run Angular CLI commands like ng build.
The folder we really care about is the app folder. The rest are:
- e2e is for the end-to-end integration tests (as opposed to unit tests).
- environments is for setting up your development and production environments (plus any others you want)
- assets for images, wav files, etc
- Misc stuff like css, index.html, favicon, and more. Mostly this stuff we don't need to worry about. Index.html, for example, just loads the root component--it's not a rich web page like you might find with other templates.
In the app folder we will find our components, which is where the work is done. Each form from our Windows forms app gets its own folder under \app\components: in ths case there's only form1 so that's the only folder created: src\app\components\hello\form1.
Each form gets three files: a css file, a typescript file, and an html file. They're pretty simple:
The .ts file lists all the required imports to make the app work, defines this component, exports the class, and constructs all the standard pieces a WebMAP app needs to run:
Style sheets and HTML
The remaining two files are super simple. The css file has a class for every HTML element, which is basically every control on the form:
Note the absolute positioning of all the elements: it's necessary to make the form render in the browser like it looks on Windows.
It's not going to be a super-slick responsive web look and feel: it's supposed to be a close to the Windows user interface as possible so the users/customers will not need re-training when the app is deployed. Of course, if it makes sense for you, you can always jack the css later to make the app look however you want.
Finally, let's look at the generated HTML:
Each control on the form gets its own HTML element tag--and they are all named "wm-[some control type]". The ids are set to the actual object name in our source code.
Two things to notice in the HTML: there is no references to the Kendo framework, and there are no references to anything specific to Angular.
We like Kendo and Angular very much, And I'm sure lots of other folks do as well. But not everyone has made that particular lash-up their standard for web dev. So one of our design goals for WebMAP5 was to de-couple the generated code from the framework and the UI control set. We already know some additional control libraries will be implemented (stay tuned for announcements later this year) and at some point someone will build a case for using PrimeNG or React instead of Angular. In the past replacing either Kendo or Angular would have meant ripping out a whole lot of code and building multiple, parallel versions of WebMAP. With WM5 it only means changing some config files to use different packages (once the packages are build, of course).
Those packages hold the code that binds both Kendo and Angular to our components. They are source code, so there is no long-term dependency on Mobilize for your app. Over time we will be enhancing them and making those enhancements available to our customers post-migration, so as they extend and maintain their new apps they can continue to use the architecture and code patterns we've created. Or, they can do something entirely different, like write more "normal" Angular components.
That has huge benefits for our customers--not only can they switch a previously-migrated app from one MVVM framework to another post-migration, but they will at some point have the ability to mix and match control libraries--possibly to implement a control from one library that isn't available in their default set.
Building the front end
Once the app has been migrated, we simply use the Angular CLI to install all the packages (using yarn or NPM) and then do ng build. That creates the wwwroot folder in the source tree. Then we can go back to the ASP.NET Core sln file and build and run it from Visual Studio 2017.
And it will run perfectly so we're done, right?
Not on your life.
Unless you are migrating something as trivial as this app, there will be work. Code that accessed the file system, or the registry, or attached hardware devices, or invoked the Win32 API directly (unmanaged code) will have to be re-worked. You can't just print from your app anymore; you'll have to invoke some kind of web service that can, for example, create a PDF, store it, generate a URL and hand that URL back to the user. The user can then download the PDF and save it or print it from a local resource like Acrobat.
Ok, that's enough for today. I hope you've enjoyed our tour through WebMAP's app architecture and that we didn't lose you. Be sure and ping me for a demo of all this--it's way cooler to see than to read about. Thinking about a web migration yourself? Set up a meeting to find out about getting your code analyzed and migrated.