2005 2006 2007 2008 2009 2010 2011 2015 2016 2017 aspnet azure csharp debugging elasticsearch exceptions firefox javascriptajax linux llblgen mongodb powershell projects python security services silverlight training videos wcf wpf xag xhtmlcss

CSS Architecture Overview

As a technology architect who has an emphasis in web architecture, one thing that I find that most ASP.NET completely misunderstand is the concept of CSS architecture.  It's incredibly important to learn that CSS is not simply "styling". This is one of the most common misconceptions about CSS in existence. CSS is more than the silly “style” attribute on XHTML elements. If that were the case, then none of us should ever rely on CSS as the “style” attribute does little more than dramatically increase the coupling between page structure and style.

Fortunately , however, CSS is more than simply "styling". In fact, CSS is an acronym that stands for Cascading Style Sheets. It's not just some nice marketing acronym used to make the technology sound cool, but is rather a very well thought out acronym that explains CSS very well. When most people come to CSS, they only look at the middle letter ("style") and completely ignore the other two letters completely. You need to understand each of the letters in order to fully grasp the architectural power of CSS.

The third letter represents CSS is "sheet". This means that CSS is a technology designed to be placed by itself in its own file.  By keeping your CSS rules away from your XHTML structure you are maximizing the potential of your system be removing all coupling and maximizing cohesiveness. That is, your XHTML is doing what it does best by representing the page structure, leaving CSS to do its job by focusing on the visual elements. There is no sharing of responsibilities and the aren't directly tied to each other, thereby allowing reuse of your CSS rules.

There are secondary reasons for doing this as well. One of them deals with manageability.  Instead of being forced to change each "style" attribute on each element across multiple files manually, you now have a centralized place for your style.  Saying "it's just one 'style' attribute, what's it going to hurt?" is a sign of laziness and unprofessionalism that will leads only to more people saying the same thing leading to a complete nightmare of spaghetti code. Imagine if people did that with C# and ASP.NET: "what's the big deal? It's only one script block." You can destroy anything by taking cutting corners.

Another secondary advantage of keeping your CSS in "Style Sheets" (CSS sheet) is that it keeps your client download time to a minimum. If you keep your CSS away from your ASP.NET/XHTML structure, your client web browsers can cache the XHTML document and CSS page separately.  When the ASP.NET/XHTML page changes, the web browser doesn't need to get all the CSS information again. In the same way, if you need to change the "style" of something, you can do so in the CSS sheet without affecting anything else. If you kept your CSS either in the "style" attribute as a sloppy blob of CSS rules in a <style/> element, then even the slightest color change is a modification of the ASP.NET/XHTML structure leading to a recompilation.  You may have killed your page cache as well.

The cascading nature of CSS, or to the “C” in CSS, is also at the heart of CSS architecture. If you manage your CSS sheets correctly, then you should have a system where you can literally change one file and have it reflect across potentially thousands of pages. Your changes will naturally flow from XHTML page to XHTML page, from CSS to CSS, and from parent elements to child elements with well thought out, virtually object-oriented element style overriding. Trying that with HTML or with CSS coupled to your XHTML elements or pages!

By working with CSS as true CSS, not simply as a nice technology to change font sizes and colors, we are able to take the potential of CSS to its logical conclusion: CSS themes. If you create a set of CSS sheets that specify the images, layout, colors, and various other style related aspects a specific look and feel, then you are in the perfect place to allow themeing of your web site.  If the term "theme" doesn't appeal to you, what about the term "branding"?  A few years ago I was involved in a project for a major fast food chain who had about 10 different brands.  They basically wanted 10 different store fronts, which made the resident e-commerce developer about flip out.  However, using a properly designed CSS architecture, I was able to provide a simple, yet powerful branding model.  First, I defined the XHTML structure based on their semantic representation.  Second, I applied a colorless and image-less CSS page which gave each website its element positioning.  Third, I gave each brand its own folder with its own root CSS page and its own images and other media files.  All the developer had to do was look at the URL path to obtain the brand name and then change a single CSS page between brand.  The developer was actually able to sleep that night.

As you can see from this story, CSS themes can be very powerful and save a lot of time.  You could event go more complex in your CSS themes.  For example, you could use a CSS coordinator.  Then is when you attach a single CSS sheet to your XHTML page and have that single CSS sheet contain a series of “@import” statements.  You could then actually change the look and feel of your entire website without ever touching the ASP.NET/XHTML structure and thereby never forcing a recompile anywhere.  I often use this technique to coordinate a CSS page for screen size (800.css, 1024.css, 1280.css) with a theme (plain.css, green.css, blue.css), with a core feature set (report.css, membership.css, landing.css-- which would be tiny, so your landing page is very quick to load).  This technique should look familiar to anyone deep into object-oriented design as it's similar to some of the GoF structural design patterns. Having said that, this is not always a required technique and sometimes it can lead to caching problems itself. For example, how will the page know to get the new CSS sheet? Sometimes it's OK to invalidate cache or to force a recompile.

Another reason for proper CSS design that is continually growing in importance is media specific CSS. Say you created a screen for management that allows simple report creation. You put a set of ASP.NET controls next to the report to allow management to refine the report data. How can you allow management to print the report without printing the ASP.NET controls? How can you turn off the colors of the report to maximize print quality on a black laser printer? How can you remove the application header from the form so that the report prints professionally or to make sure the document prints on one sheet? All these things are possible with media specific CSS. By having one structure stating the content of the document you have a base level entity that can then be transformed to various output media. Media specific CSS works for more than just printers. If you thought ahead in your web architecture and therefore created a proper semantic representation of your XHTML elements and separated your CSS from your XHTML, you can easily add light-weight mobile support with very little effort. When a web browser views your page it will display in all its glory, when a printer accesses the page the buttons and header will be gone, and when a mobile device views the page the sidebar is now hidden, the fonts are now smaller, text shows in place of images, and the menu is now abridged.

You can easily add media specific CSS to your documents by placing more <link /> elements in your XHTML head element.

For example, the following will set a general CSS page, a print theme, and a mobile theme.

<link href="Style/ClassicTheme/default.css" rel="stylesheet" type="text/css" />
<link href="Style/ProfessionalPrintTheme/default.css" media="print" rel="stylesheet" type="text/css" />
<link href="Style/SimpleMobileTheme/default.css" media="handheld" rel="stylesheet" type="text/css" />

One thing you may want to keep in mind about this is that the iPhone is not considered a “handheld” device. To add a media specific CSS page to the iPhone, please see this article.

It's hard to overestimate the importance of proper CSS architecture, yet I find that most web developers have never even heard of this before.  I suspect that it's because its a fusion of diverse topics which with most web developers aren't familiar.  For example, many ASP.NET developers I work with know software architectural principles, but can't even spell CSS.  Other times, I'll see awesome web designers who have no idea what software architecture is.

XmlHttp Service Interop - Part 3 (XML Serialization)

In this third part of the series, I discuss how to manually create an XML service and a SOAP service using XML serialization to maximize the flexibility in your service interop work. The technique allows you to very quickly accept just about any XML format from the wire and work with it in a strongly typed manner in your .NET applications.

Reflecting Graph Video Demo

For those of your who have not installed Silverlight, below is a link to a video of the demo. As you will see it works perfectly in Firefox and IE.

Links

Reflecting Graph Silverlight Demo

In one of my Ajax applications I wanted a REALLY cool interface for some of my data modeling. I was a bit stuck until I heard that Microsoft published a beta of Silverlight 1.0 (an actually working one too!) This of course opened up an entirely new planet of new design possibilities.

The design that I came up with was a tree model where each element was a node in a mesh like structure where the user can move the elements as well as the entire structure in one smooth motion and where the user can zoom in and out with their mouse scroller... something that was incredibly simple to build in Silverlight.

To demonstrate what I built, I would like to use toned-down version of the same thing to show a simple type reflector with a Silverlight interface. In this demo, simply select an assembly and select a type. The type will show up as a graph with branches for reflected members, organized by methods, properties, and events.

The mechanics of this is actually really simple. First, define a few canvases so that an inner canvas can scale and translate to give the effect of a zoom and canvas movement. Second, have a method that accepts a JSON structure containing the model for your tree. In the iteration plot the ball element, the text as as well as a line that goes from itself to its parent. The trick in this step is to get the math right to know where exactly to plot the element. I'll discuss this in a bit. Lastly, watch for mousedown, mouseup, and mousemove events on the elements and the on canvas as well as mouse scrolling events on the canvas.

Placing the elements on the screen is really just basic geometry. We know that the first element can go anywhere and that its sole purpose is to set a positioning basis for all other elements. Plotting the children is just about as easy. For perfectly symmetrical elements, you just have to plot them at equal points from each other around a 360 degree radius. For mathematical details on this, see the essential mathematics page below.

Having symmetrical elements is all well and good, but it's ugly and nasty. [See image 1] So, to take it a bit further, I played with the angle a bit. If the element was the first child, I just plotted it normally via symmetry. If not, make the angle an increment of 45. This will just make the children the same length from each other regardless of how many there are. [See image 2] After this, I scaled down the separation of the elements by how many elements there were. [See image 3]

Next, I wanted to make sure the children were pointing in the same general direction their their parents pointed in. So I subtracted the angle of the parent (minus 90) to make it go in the same general area. Remember that all the elements are grouped together, so now we are moving groups of elements, not just a single element. [See image 4]

At this point it doesn't look too bad, but the child groups don't really line up with their parents. For them to line up I needed to add 45 degrees plus half the radius of the entire child set (another 45 degrees scaled by how many children there are). [See image 5]

Now we have something that looks like it it could grow nicely... however, it would be nice if it didn't look like a robot built it. To give it a more organic feel I added a random angle to every element. No, it's not the most sophisticated method for creating a more natural look, but it does work rather nicely. [See image 6]

As far as the events are concerned. If you get a mousedown on an element, you are in dragging mode and when you get a mousemove, adjust the element, text, and line accordingly. Silverlight will automatically redraw the line based on the new X, Y endpoint of the line. If you get a mouseup, then you are no longer in dragging mode and mousemove, doesn't do anything. If you get a mousedown that's on the canvas, then you simply need to adjust the translation of the canvas. If you get a mouse scroll simply, adjust the scaling of the canvas. It's extremely important to take the scaling into effect when you work with the moveable elements as the coordinate system completely shifts. In the provided demo, I added a few adjustments for this, but it could be much better it a live version.

As a closing note, this demo can also act as an example for an asymmetrical schema Ajax service. The service I wrote here accepts an XML message, but responds with JSON data. It's important to remember that the focus of communication is on receiving, not on transmission. If a person from France and a person from German want to have a conversation and each CAN speak the other's language, but understand their own flawlessly, the one from French may speak German so as to maximize communication and the person from German may speak French to the same end. So in this example, JavaScript speaks XML to .NET, which can easily deserialize it to a usable object and .NET speaks JSON back to JavaScript for easy direct use.

Related Materials

JavaScript Repeater Data Binding

In a previous post, I wrote about a way to convert JSON to XAML. The sample I provided with that post didn't really stop with a simple conversion example, but it also demonstrated how to create an use a simple JavaScript data binding repeater. It's just something I threw together in two minutes to bind an array of objects to a div to basically do in JavaScript/XHTML what ASP.NET does with the Repeater control. I think many people will be interested in this technique to see how they can bind data to a browser in a more efficient way.

As far as my requirements, I wanted this to be like ASP.NET in that the data is bound from a data source matching the fields in the data source objects to the data fields declared in this repeater and after all is said and done, the original declarative code should disappear. As far as the data source, I wanted it to be a series of the same type of object... kind of like a generic List.

So, to start off with, I simply declared the code that I wanted to write as the client. Some people call this the 'Sellsian' method (after Chris Sells at Microsoft), though I simply call it... common sense (as I honestly suspect Chris would too!). So, here is the declarative code I wanted to write for my data binding:

<div id="rptData">
    <h2>Title</h2>
    <div id="title" class="bind"></div>

    <h2>XAML Output </h2>
    <div id="output" class="bind"></div>
</div>

In this situation the data source fields are matched to element with the bind class and the element id. This is much like <%#Bind("") %> in ASP.NET.

On the other side, I would like my data source to be in JSON format and I would like to be able to bind in a way that 'feels' like a static class. Here is what I decided on:

var dataSource = [{
        title: 'Ellipse',
        output: Xaml.CreateXamlFromJSON(jsonElement1)
    }, {
        title: 'Rectangle',
        output: Xaml.CreateXamlFromJSON(jsonElement2)
    }, {
        title: 'Canvas',
        output: Xaml.CreateXamlFromJSON(jsonElement3)
    }
];

DataBinder.BindTextRepeater(D('rptData'), dataSource);

In the sample above you can see that I have a data source with 3 objects with the object being defined with the interface of a string field named 'title' and another string field named 'output'. Furthermore, I wanted to call the method what it is: a text repeater, not a fancy object repeater (though building that shouldn't be much more difficult), so my static method is called BindTextRepeater and accepts the declarative repeater object and the data source as parameters. In my examples I use the D('id') syntax where D is simply an alias for document.getElementById. I know some people use a dollar sign for that, but that just looks really weird to me.

Now onto the code. Here is the basic shell:

var DataBinder = {
    BindTextRepeater: function(obj, ds) {

    }
}

The first thing we do in this situation is look at the data source and see what the objects look like. For this we simply need to create an array to record what fields we are looking at and iterate through the object to record it's fields. Put another way... we simply need to do simple JavaScript reflection and record the object interface, something that's incredibly simple in JavaScript.

var fields = new Array( );
for(var f in ds[0]) { fields.push(f); }

Now that we know what the object looks like, let's iterate through the datasource and bind each field to it's proper place in the repeater. This is what the rest of the method does and it should be fairly self explanatory, except for the following things:

First, I said that data is bound to fields with the 'bind' class. What if you had your own class on it? That's not a problem. JavaScript classes are a bit like .NET interfaces (where as JavaScript ids are a bit like .NET classes), so you can "apply" (or implement in .NET) a few of them. So, if you wanted the apply the class "message-log" to the bindable element, you would simply have the following:

<div class="bind message-log"></div>

In this case this is possible because I'm simply checking to see if the class STARTS with "bind", rather than simply checking to see if it IS "bind":

if(obj.childNodes[e].id && obj.childNodes[e].className && obj.childNodes[e].className.substring(0, 4) == 'bind') {
    /* ... */
}

Second, if the element if found to be bindable, the method looks through the fields array to see if that element has data for in the specified data field. If so, it binds. If not... there's not much it can do (though ideally you would throw an exception). One thing to note about this is that it replicates the element and binds the text as a child. This is seen by the following line:

var bindableObj = obj.childNodes[e].cloneNode(false);

When you clone a node, you can say true, which means to clone it's children, or you can say false, which means to clone only that particular element. In this case, we don't need the children as this is a text repeater and we are going to put our own text as a child. If we were to say true, we would have to go out of our way to remove the children.

If the element is not found to be bindable, it copies the element and it's children as can be seen as the cloneNode(true).

Third, after the data object is ready you have a duplicate of the original repeater, but now filled with data from the data source. This data object is then bound to the browser's DOM as a element immediately before the repeater template. After all data objects have been bound, the original repeater is removed. Thus, you replaced the repeater template with data bound controls and you're done.

Here is the final implementation of the BindTextRepeater method:

var DataBinder = {
    BindTextRepeater: function(obj, ds) {
        var fields = new Array( );
        for(var f in ds[0]) { fields.push(f); }
        
        for(var r in ds) {
            var outputObj = DOM.createElement('div');

            if(ds[r]) {
                var d = ds[r]
                for(var e in obj.childNodes) {
                    if(obj.childNodes[e].nodeType && obj.childNodes[e].nodeType == 1) {
                        if(obj.childNodes[e].id && obj.childNodes[e].className && obj.childNodes[e].className.substring(0, 4) == 'bind') {
                            for(var i in fields) {
                                if(obj.childNodes[e].id == fields[i]) {
                                    var bindableObj = obj.childNodes[e].cloneNode(false);
                                    bindableObj.appendChild(DOM.createTextNode(d[fields[i]]));
                                    outputObj.appendChild(bindableObj);
                                }
                            }
                        }
                        else {
                            outputObj.appendChild(obj.childNodes[e].cloneNode(true));
                        }
                    }
                }
            }
            obj.parentNode.insertBefore(outputObj, obj);
        }

        obj.parentNode.removeChild(obj);
    }
};

Using this same approach of templating XHTML elements and reflecting JavaScript JSON data sources, you could actually create a full scale data binding solution for all your client-side data binding needs. Furthermore, since we used a JSON data source we can now bind data directly from JSON services accessed via Ajax techniques. Lastly, as I hope you can see, there wasn't really much magic in this example and absolutely no proprietary technology. It's simply a usage of what we already have and have had for many, many years.

Links

Powered by
Python / Django / Elasticsearch / Azure / Nginx / CentOS 7

Mini-icons are part of the Silk Icons set of icons at famfamfam.com