In the first part of this series, we spent some time discussing how complex web application coding can be. Web sites are simple; web apps are hard.
The good news is that WebMAP solves most of your problems, by an enormous amount of cumulative cleverness from our development team.
- You can use coding skills you already have
- You can read the code
- You can add to the code without going crazy
- You can get a high-performance web app that's actually simple
- And we do it all with source code, not voodoo binaries.
Let's look at some code
What if we migrated our HelloWorld app from part 1 to the web, using WebMAP? What would that look like?
Which super-complex method, described in Part 1, did we choose to create this amazing web app?
None of the above.
WebMAP--like we said earlier--hides a lot of the complexity. Ok, basically all of the complexity. Let's look at the server-side code (remember a web app has to have a server component and a client that runs on the local browser):
If this code looks suspiciously like Winforms code, it's by design. In fact, there are only a few subtle differences between this code (which is now running on ASP.NET Core) and the original C# code (which ran on Windows desktop only):
- The Form1 class inherits from Mobilize.Web.Form (we'll get back to that in a minute)
- The form declaration has an attribute: [Mobilize.WebMap,Common.Attributes.Observable]
- There are no "using" statements
That's it. No controllers, no views or viewmodels, no models, just what appears to be almost exactly the same code that worked for a desktop app. How is this possible?
My favorite things...
Remember Julie Andrews singing My Favorite Things in "The Sound of Mucus"?
Raindrops on roses
And whiskers on kittens
Bright copper kettles and warm woolen mittens
Brown paper packages tied up with strings
These are a few of my favorite things
Ok, that was mean. But packages really are one of my favorite things: both the kind I get from Amazon and the ones that handle dependencies in my apps. Let's look at the packages that our migrated HelloWorld app has:
Ok, so this should make Julie pretty happy--lots of packages. And this is where the magic happens in WebMAP--these DLLs let the server side code be highly decoupled from the web server housekeeping and the client side.
The Form class
Again--staying with the server side--the Mobilize.Web.Form class is used to instantiate all our forms, build the UI, and handle events. If we look at the Object Browser here's what we'll see:
Some of these methods and properties should look pretty familiar (Show(), CancelButton, etc) and some not (_Mobilize_GetChanges()). Remember, the goal of WebMAP is to migrate your Windows Forms apps to web, so we aren't going to have a bunch of properties or methods for classes that aren't representative of what you find in Windows. (NB: WebMAP can support a variety of input formats, including non-Windows stuff like PowerBuilder. For the purpose of this blog, however, let's just focus on Windows Forms.)
Observable, Weaving, and AOP
The other big change referenced above is the Observable attribute we see for the class Form1.
Now you've got to get your geek on.
Likewise, in our designer file (Form1.Designer.cs), we'll find a different attribute on the class: [Mobilize.WebMap.Common.Attributes.Intercepted]. In this class we create all the visual controls that will be on our form. The Intercepted attribute tells the Visual Studio compiler that this is a place to inject code.
You've probably used inversion of control (IoC) AKA dependency injection in code somewhere, right? Well, this is very similar. You may already be familiar with it: Aspect-oriented programming or AOP. AOP allows us to "de-clutter" the code you have to deal with from all the complexities needed to handle issues common to web applications. Like, for example, modality.
WebMAP takes advantage of the open-source "Roslyn" compiler platform in Visual Studio. Among other things, this platform offers real-time code parsing (which is how Intellisense works). WebMAP uses that capability to inject code from helper classes into "Intercepted" code and create new, expanded C# files. Since the compiler front end is running all the time, as you edit those user-facing C# files, these expanded C# files are always being changed as well. Press F5 to kick off a build and the compiler knows to use the expanded files--not the files you were editing--for the build process. Injecting these classes where necessary is what we mean when we talk about "weaving."
Ok, that sounds really complicated. But it's not really. And in the 3rd installment of this overly-long blog, I'll explain why.