Pattern-Based XML Literals Prototype: ASP.NET Core Revisited

This is my third post in this series about pattern-based XML literals. In my last post I showed how you could apply the concept to the Xamarin.Forms library via extension methods to build a cross-platform mobile app in VB using what are essentially “XAML literals” to describe your UI. In this post I’m revisiting the web and showing how someone could use the exact same pattern to not only make a dynamic ASP.NET Core MVC app but how to do so while reducing code by 50-80% using one classic idea!:

Yep, web controls. I know. But these aren’t like the ASP.NET WebForms web controls. There’s no view state or post-backs here; it’s still all MVC. These controls just know how to render themselves and that counts for a lot!. And, as I said earlier, this is the same XML-pattern at the language level that I used in my Xamarin video, the only thing that’s changed is the types that are being constructed (and they were built with the pattern in mind so no need for extension methods). Also, I temporarily merged in my top-level code prototype to get back that sweet full-file top-level XML expression experience! I didn’t change the pattern any, which is a good sign.

My personal rematch with an old challenge from the early 2000s…

From September 1999 to June 2003, I was in high school (I’m currently 34 for those of you doing the math). I was in our high school computer club, tasked with building what was then our high school website. I wanted to liven up the site with “DHTML” (i.e. JavaScript) that would create a drop-down menu instead of requiring navigating the site through clicking through a tree of links. I thought I was soo cool.

I got some examples off of some website, (it might have actually been called dhtml.com or something) but the menu was soo tedious to implement. I vaguely recall making a VB6 app that would generate the menu from an indented text file, it was that tedious. Compare my high school experiences with this declarative masterpiece:

And all I had to do was spend the next 7 years coding, get a job at Microsoft on the programming languages team, design programming languages and build compilers for 8 more years, and voila! It’s so simple!

Full comparison of source code and HTML output here.

A Declarative and Object-Oriented Approach

Even just using plain HTML/CSS/JavaScript, it’s gotten better (and I’ve gotten better) but the web can still be pretty tedious compared to what I’m used to and love about traditional desktop app programming. Sure, HTML is declarative but depending on what you have to declare one person’s declarative is another person’s spaghetti-code and generating certain common, exciting, interactive web experiences can easily liter you page with tons of implementation details.

Encapsulation FTW

Pattern-based XML literals let me use my object-oriented instincts of abstraction and encapsulation in a crazy-productive declarative way. And I actually experienced one of the benefits of this encapsulation immediately first hand. While writing the carousel example I started from the ASP.NET Core sample but later moved to the w3schools example because one of their pictures was named “Chicago.jpg”. Little did I realize that the W3Schools was using Bootstrap 4 while the ASP.NET Core sample I had started with was using Bootstrap 3. Well, in between 3 and 4 Bootstrap changed a few things (understandably):

  1. The CSS classes for carousel items went from class=”item” to class=”carousel-item”
  2. The CSS classes for carousel controls went from left carousel-control to carousel-control-prev
  3. The glyphicon library that had previously been included by bootstrap no longer was so the carousel controls which used it no longer rendered correctly.

In short, nothing worked. Had I been directly using this carousel code (or some other element) across a real site, at that point I’d have to manually go through all of my pages looking for divs with class “item” and manually update them—for EACH ITEM. Once I realized what was going on, I just updated my Carousel control class once to generate different output for items and I was done. Next run of the app the page rendered correctly without having to change any of the markup in my Index.vb file.

Summary

Controls are perhaps the most empowering abstraction to ever touch my life. Entire ecosystems of control creators and vendors sustained the VB community for decades. And a world where there aren’t re-usable control components to hide and handle basic rich UI experiences is an incredibly complex one that I’m not particularly interested in coding in.

Reducing complexity through abstraction, encapsulation, and polymorphism is a very object-oriented approach to the web. But to be able to use them it helps to have “objects all the way down” and traditionally that would mean giving up the declarative simplicity of markup languages like (X)HTML. With pattern-based XML literals that doesn’t have to be the case. This potential feature massively scales up the expressivity of the XML literal-based ASP.NET Core view engine I showed back in May and opens the door for even more cool stuff I’ll show in my next post.

I do want to talk about the idea of what a real (not made for demo purposes) web controls library would look like but that’s a separate conversation from discussing this prototype so I’ll be giving that topic its own post as well.

Until then, as always, thanks for reading, thanks for watching! Please share this post, and let me know your thoughts in the comments below and/or on Twitter.

Regards,

-ADG


P.S. As in my last series, I’ll upload all of my notes from implementing the prototype in a GitHub issue after the last post in the series. Don’t sweat the specifics of the pattern too much, they’re subject to and very likely to change. This post took me much longer than usual because I had to take a refresher course on CSS, JavaScript, the DOM, and write an entire naive implementation of a self-rendering class hierarchy modeling all the HTML elements used in that video (don’t worry, inheritance took care of a lot of the work).

Credits to these sources for their help:

  • W3Schools – Expander, Menu, Carousel examples. This site is an indispensable resource to all things web.
  • HTMLDog – Multi-level Menu example.
  • Jason Chatonda – Sound editing, because this video had a lot of esses in it. Imagine Daffy Duck soliloquizing on the superior splendiferousness of XML, expanders, menus, carousel scripts and CSS specificity.

9 thoughts on “Pattern-Based XML Literals Prototype: ASP.NET Core Revisited

  1. Nice work.
    – How did you get intellisense support for the new tags? XSD schema doesn’t work for me.

    – If I want to add some repeated controls using for loops, or use if statements to choose the suitable control to add, this will need to call some functions to generate those sub xml literals, or it can be done inline by using lambdas, but this approach makes the code longer. With your Top-Level Code Prototype, it is possible to write the code directly to be added in implicit function. I suggested to use “ as a quote for this purpose.
    Thanks

    Like

    • Sorry, I always forget to encode symbols:
      I suggest to use <( )> as a quote for this purpose.

      Like

    • I didn’t implement any IntelliSense support. I just hit Paste in that video because typing slows down the video a lot. That said, I think adding IntelliSense support for the XML pattern itself will be straightforward. In the simplest case you’re just getting back property symbols like any other member access. But even when the properties aren’t real you can create a new symbol type that represents the … pseudo-virtual property representing that attribute. This is /very/ similar to what happens when you use tuple member names. Even though there’s not real property called x in the `(x As Integer, y As Integer)` tuple type, the compiler creates one. Also similar to the `dynamic` pseudo-type used in C#. My point is, there’s plenty of prior art on creating erased symbols where there aren’t ones really and we can use that to power a completion system easily.

      As for repeater controls, you can always use an embedded expression for loops, as well as the `If(,,)` operator. Beyond that, the Carousel example I gave is very much an example of a way to address that problem. I do have a proposal on the lambda thing too because that’s necessary for template controls to work well with the Xamarin.Forms example I gave. Look out notes on all of that next week!

      FWIW, I like and and in some cases it wouldn’t be ambiguous to just use {}. We can chat about those options when I post the GitHub issue!

      Like

      • OK.
        Note that XAML use data templates to repeat data controls and bind them to the data source. My opinion is it makes XAML more complex, and I want to simplify it by using Razor style: Writing VB and C# code withinn XAML in WPF, UWP, and Zamarin forms. This will be easier in VB xml literals using your Pattern based XML, but needs a simpler form to embed VB code as discussed above. Using {} can cause ambiguity with array initializers used in the embedded code, and they need to be escaped inside XML not to be treated as regular text, or vice versa.
        In fact, we need a symbol that can be used both in attribute values and outside XML tags.

        Like

  2. Pingback: Pattern-based XML Literals Prototype: Client-Side VB.NET Running in the Browser (sorta) | Anthony's blog

  3. I suggest you make use of the mshtml library instead of rebuilding wpf-like controls.
    can you get the source code for mshtml.dll ? Currently it works on Framework only, so it has to be migrated to .NET Standard
    It ha classes for each HTML element.
    Still, we need a way to write CSS as WPF Styles. Or in fact, I hope we can have the best of both, because I find WPF Styles too verbose and CSS selectors are better, but need to be written in a WPF way.

    Like

    • You and I are going to sit down and really talk about this idea. It’s separate from the language proposal but I think it’s something someone should do. Maybe you. Maybe both of us!? I don’t think that the different coding styles are mutually exclusive–multiple levels of abstraction can be supported.

      Liked by 1 person

Comments are closed.