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

Coders and Professional Programmers

I have to say it: there is a severe lack of skill in the technology world today, even among senior-level developers.  Perhaps I just have too high of standards, but when I see a person working in technology, I kind of expect them to have the requisite skill set for the job.  It always amazes me when I see a developer, even a senior-level developer, who doesn't know the basics of their own system (i.e. an ASP.NET developer who doesn't understand CSS positioning or a .NET developer who doesn't understand the framework design guidelines).  They may have degrees and have years of experience, but they have no actual skill.  It's always concerned me a bit that people have so little skill, but I wasn't able to put the problem into words until recent.  Well, that's not completely true.  An old friend of mine put it into words years ago, but it wasn't until this week that I was reminded of my own story.

Last week I was in a bookstore looking at a few design patterns books and a "1960s NASA engineer" type of guy in a white shirt and tie came up next to me, dressed in extremely casual blue jeans and a black shirt, looking at similar books.  I noticed he picked up a rather lame design patterns book, so I took it upon myself to hand him the GoF book saying "This one is the classic".  He thanked me and started to flip through it.  A minute later I realized that I couldn't resist asking: "So, what exactly are you looking for?"  He mentioned he was looking for a book demonstrating a state machine.  I grabbed another book, flipped the pages a bit and handed it to him saying "page 486".  His response was "Wow, thanks... so, where did you go to school?"  I have to admit that I've gotten many questions in bookstores, but I've never been asked that one FIRST.  The way he asked the question wasn't so much out of sincere curiosity, but more out of arrogance.  It felt like wanted to compare his degrees to my own.  I simply replied "School?  What?  You're looking at it...", pointing to the wall of computer books.  He immediately shut up and stepped away.  I'm not sure if that qualified me as a leper or if I just castrated the man's sense of academic accomplishment, but, regardless, that conversation was over.  However, a few moments later I found a book I was looking for and said "AHA! This will make them think!"  The same man curiously asked "What do you mean?"  I explained that I was looking for a book to recommend to developers to help then get a clue about software architecture.  The man gave the look of familiar with my situation and said something I haven't thought about in years: "Oh yeah... I know exactly what you mean.  Some people just don't get the difference between a coder and a professional."  At that point I had my flash back to a time of my life almost 6 years earlier... back when I was a coder.  It was a lifetime ago and I had all but repressed until recently.

The year was 2001 and I was a PHP programmer, Linux hacker and Math major at Kansas State University.  My idea of programming was looking at the PHP documentation, reading the PHP documentation comments and copy/pasting until my application was built.  I figured I knew what I was doing because I had already been in the field for 5 years; I was only now going back to school after a 3 year academic hiatus.  I would mix PHP, HTML, JavaScript, and tiny bits of CSS all in the same page in an absolutely unreadable pile of slop, "but it worked".  A friend of mine from high school, who by this time was a Microsoft employee, looked at what I was doing and mentioned to me in his usual blunt style: "Dude, that's not programming, that's slop coding.  You don't even have a data access layer, do you?"  Completely ignorant of the first clue of what he was talking about I said "Well, sure I do, PHP has a connector to mySQL.  I'm not accessing mySQL directly; I'm using the PHP API."  Thinking back on it I think he wanted to punch me in the face from that painfully ignorant comment."  Truth be told, I was not a professional programmer even though I had 5 years of crazy JavaScript development, 2 years of Ajax development, 2 years of ASP development, 2 years of SQL Server development, and 1 year of PHP development under my belt; I was only a coder.

After that, I spent a tremendous amount of time going back to the books and learning more about technology.  In high school I had some of the lowest grades in my classes because I spent my nights reading video game programming,  graphics programming, C/C++ programming, computer history, networking theory, Novell NetWare, and web development books.  In college, the pattern was being repeated in a the same familiar way.  I spend a ton of time studying all kinds of new technologies, one of which being XHTML/CSS design, all to the destruction of my meaningless academic career.  After finally breaking free from the tight bondage of academia I went to work for a few places as a PHP developer.  After one of two complete waste-of-time contractor positions I finally realized that it was time to cross over to .NET.  So, I spend an incredible amount of time studying .NET concepts, ASP.NET, the Framework, and C# technologies.  After a month I took and passed the 70-315 (ASP.NET) exam and the 70-229 SQL Design exam a week later.  From there I went to study the 70-320 (.NET components) and 70-228 material (SQL Administration).  Around that same time I realized that Mozilla finally released a product that didn't suck.  Not only did this product not suck, it was by far and away the most revolutionary piece of technology since the Internet itself: Mozilla Firefox 1.0.  With that I also started studying web standards much more deeply.  Being former Linux hacker, I wasn’t and still am not brained washed by the Microsoft extremist cult, so I've always been open to having the best technology regardless of vendor.

At this same time I realized that I really, really wanted to be a professional programmer and not a coder in any way.  So, I said goodbye to Visual Studio and took back my EditPlus to do all my .NET work.  I was not about to rely on Intellisense to do my work for me and already knew the danger of learning a new technology by error messages.  For the next year I deliberately did all my development without color syntax and without Intellisense.  I've never had any respect for "drag-n-drop" property developers, so I never used the designers anyhow, but now I wasn't even going to let Intellisense help me either.  If I needed to do something, guess what, I had to actually read the manual.  There would be no copy/paste slop coding and no hitting the forums every single time I hit the slightest bump.  If I had a problem, I would think about it and solve it using that technology, not simply a hack to throw some hack together.  I had enough years of wasting my time doing that.  Yes, at first, this got me into trouble, but I was determined to be a professional programmer at any cost and not a coder at all.  I wanted to internalize the systems as I had internalized driving my car.  After the initial slowdown (and the initial "being let go" from a project), I became much faster than all the other developers from the forced memorization of much of the documentation.  Whereas others had to look up how to use the Sqlconnection, SqlCommand, SqlDataAdapter, and DataSet combination, I was typing them out as if I were writing a sentence.  Around the same time I spent much time studying LLBLGen Pro, unit testing, object-oriented design (not to be confused with the entry-level concept of object-oriented programming I learned 10 years ago in C++), N-tier architecture, Modern JavaScript, and a year after that I took a block of time to study web services, MSMQ, COM+, service interop, and other communication mechanisms (most of which were later rolled up into WCF) all to the point of either complete or partial internalization.  In 2005 I was finally able to say that I am a professional programmer, not simply a coder.

As you can see from my story I know what it’s like to be a coder and I know the temptation to remain as a coder.  You think “your way” works and therefore you shouldn’t change it.  In fact, you probably hate other technologies, because their way isn’t "your way".  I can understand that too, but really it’s just a misunderstanding of that other technology.  My first ASP.NET application (a photo gallery) had absolutely no declarative code and was written with 100% Response.Write statements (I often tell people "make sure your first project in any technology is NOT a production one"; this is why).  I didn’t have the first clue what I was doing and, being a longtime classic web developer, I could not get that “magical” ASP.NET postback through my head.  Building that same application today would consist of an elegant ASP.NET custom control and two or three web forms.  I also understand what it’s like to say “...but this is how I do it in this other technology”, when in a reality that’s a completely meaningless statement.  Each technology has its own paradigms, naming schemes, guidelines, concepts, and languages.  Just because you are a Java rock star, doesn’t mean you will be able to do anything in .NET for at least 6 months.  The same goes for VB rock stars and PHP rock stars (as odd as it sounds, in my experience PHP developers have the hardest time learning .NET where as VB developers excel rather quickly-- this goes to show how hard it can be to un-link and old technology from your mind). I also know what it’s like to ask yourself “how can I do this?”  That’s what a coder asks where as a professional asks “How has this been built before in this technology; what is my precedence?”  In case you didn’t know, software development has been around for decades.  If you are running around trying to come up with a way to do something, you may be wasting your time as it’s probably been done before, the debates have probably already happened, people have probably already learned from their mistakes; you just have to accept what they've done for you, within limits, of course (i.e. C++ design patterns transfer to C#, but obviously not OOP style as .NET doesn’t allow multiple implementation inheritance).

So, if you find yourself in a place where most of your development is done doing things “your way” or the way “you have always done it” or if you ever ask “how can I do this”, maybe it’s time to break down and take some time out of your life to convert from being a coder to a professional.  It is definitely an investment, but with many great books out today (not all are so great), you could probably convert from being a coder to some level of professional programmer rather quickly (it took me a bit longer because I didn't have any role models to work under and I had no idea what the scope of the training was). There is an old computer science saying that goes something like this: "Anyone can write code that a computer can read, it takes a professional to write code a human can use."  We should all think about that and possibly post it on our walls.

To aide in the process of converting from a coder to a professional programmer, a few months ago I wrote up my requirements for a Senior-Level developer or Architect on my blog.  It should give you a shell outline for some of the technologies and topics you seriously need to have under your belt to be a professional.

Real World HttpModule Examples

Back when I first discovered HttpHandlers I remember being ecstatic that the control that I thought I lost when moving from PHP to ASP.NET was finally returned, but when I first discovered HttpModules I remember almost passing out at the level of power and control you get over the ASP.NET request pipeline.  Since then, I've used HttpHandlers, HttpHandlerFactories, and HttpModules in many projects, but I'm noticing that while many people have heard of them, many have no idea what you would ever use them for.  So, I would like to give a few examples.

The first example is really simple.  On my blog, I didn't ant anyone to alias my web site or access it in any other way than by going to www.netfxharmonics.com.  Since HttpModules allow you to plug into the ASP.NET request pipeline, I was able to quick write an HttpModule to do exactly what I wanted:

public class FixDomainHttpModule : IHttpModule
{
    public void Dispose( ) {
    }

    public void Init(HttpApplication context) {
        context.BeginRequest += delegate(Object sender, EventArgs ea) {
            HttpApplication ha = sender as HttpApplication;
            String absoluteUrl = ha.Context.Request.Url.ToString( ).ToLower( );
            if (ha != null) {
                if (MinimaConfiguration.ForceSpecifiedDomain) {
                    if (!absoluteUrl.StartsWith(MinimaConfiguration.Domain.ToLower( ))) {
                        context.Response.Redirect(MinimaConfiguration.Domain);
                    }
                }
            }
        };
    }
}

...with this web.config:

<httpModules>
  <add name="FixDomainHttpModule" type="Minima.Web.HttpExtensions.FixDomainHttpModule" />
</httpModules>

By doing this I don't need to put a check in each page or in my MasterPage.  Since HttpModules are for the entire application, even URLs accessing my images are forced to be done by www.netfxharmonics.com.

Another example is a simple authentication system for a system I was working on a while back.  The application allowed anyone logged into active directory to access it's resources, but only certain people logged into active directory would be authorized to the use application (i.e. anyone could access images and CSS, but only a few people could use the system).  Knowing that the .NET framework is the model for all .NET development, I looked at the machine's web.config to see how ASP.NET implemented its windows and form authentication.  As it turns out, it does so by HttpModules.  So, I figured that the best way to solve this problem was by creating an HttpModule, not by throwing a hack into each of my WebForms or my MasterPages.  Furthermore, since ASP.NET uses the web.config for its configuration, including authentication configuration, I wanted to allow configuration of my authentication module to be via the web.config.  The general way I wanted to configure my HttpModule would be by a custom configuration section like this:

<Jampad>
    <Security RegistrationPage="~/Pages/Register.aspx" />
</Jampad>

The code for the HttpModule was extremely simple and required only a few minutes to throw together.  If the page being accessed is a WebForm and is not the RegistrationPage set in web.config, then the system's Person table is checked to see if the user logged into the machine has an account in the application.  If not, then there is a redirect to the RegistrationPage.  Simple.  Imagine how insane that would have been if you wanted to test for security on each page.

public class JampadSecurityModule : IHttpModule
{
    public void Dispose( ) {
    }

    public void Init(HttpApplication context) {
        context.BeginRequest += delegate(Object sender, EventArgs ea) {
            HttpApplication ha = sender as HttpApplication;

            if (ha != null) {
                CheckSecurity(context);
            }
        };
    }

    private void CheckSecurity(HttpApplication context) {
        SecurityConfigSection cs = (SecurityConfigSection)ConfigurationManager.GetSection("Jampad/Security");

        if (String.IsNullOrEmpty(cs.Security.RegistrationPage)) {
            throw new SecurityException("Security RegistrationPage is required.");
        }

        if (cs == null) {
            return;
        }

        if (!context.Request.Url.AbsoluteUri.Contains(cs.Security.RegistrationPage) &&
            context.Request.Url.AbsoluteUri.EndsWith(".aspx")
            ) {
            PersonCollection pc = new PersonCollection( );
            pc.GetMulti(new PredicateExpression(PersonFields.NTLogin==ActiveDirectoryFacade.NTUserName));

            if(pc.Count < 1){
                context.Response.Redirect(cs.Security.RegistrationPage);
            }
        }
    }
}

Again, plugging this into the web.config makes everything automatically happen:

<httpModules>
    <add name="JampadSecurityModule " type="Jampad.Security.JampadSecurityModule" />
</httpModules>

Recently I had to reuse my implementation in an environment that would not allow me to use LLBLGen Pro, so I had to rewrite the above 2 lines of LLBLGen Pro code into a series of Strongly-Typed DataSet tricks.  This implementation also had a LoginPage and an AccessDeniedPage in the custom configuration section, but other than that it was the same idea.  You could actually take the idea further by checking if the person is currently authenticated and if they aren't do a check on the Person table.  If they have access to the application, then PersonLastLoginTime column to the current time.  You could do many things with this implementation that would be rather crazy to do in a WebForm or MasterPage.

Another example of an HttpModule would be my custom access control system I built into my blog.  I'm not going to paste the code here as it's just the same idea as the other examples, but I will explain the concept.  Basically I created a series of tables in my blog's SQL Server database that held information on access control.  In the Access table I put columns such as AccessDirection (allow, deny), AccessType (IP Address, UserAgent, HTTP Referral), AccessText, AccessMessage, and AccessRedirect.  My HTTPModule would filter every ASP.NET request through this table to figure out what to do with it.  For example, I could block an IP address by creating a table record for 'deny', 'IP Address', '10.2.1.9', 'Your access has been denied.', NULL.  Immediately upon inserting the row, that IP address is blocked.  I could also block certain UserAgents (actually this was the original point of this HttpModule--bots these days have little respect for the robots.txt file).  I could also block requests that were from a different web site.  This would allow me to stop people from leaching images off my web site for use on their own.  With a simple HttpModule I was able to do all this in about an hour.  By the way, one record I was tempted to create was the following: 'deny', 'UserAgent', 'MSIE', NULL, 'http://www.getfirefox.com/'.  But I didn't :)

Now when would you use an HttpModule versus an HttpHandler?  Well, just think about what the difference is.  An HttpHandler handles a specific address pattern for a specific set of HTTP verbs, while every request in an application goes through an HttpModule.  So, if you wanted to have an image creator at /ImageCreator.imgx, then you need to register .imgx to IIS and then register your image creation HttpHandler in your web.config to handle that address (in case you forgot, web browsers care about the Content-Type, not the file extension.  In this example, your HttpHandler would set the Content-Type as 'image/png' or whatever your image type is.  That's how a web browser will know what to do with a file.  It has nothing to do with the file extensions; that's just for IIS.)  On the other hand, if you wanted to block all traffic from a specific web site, then you would create an HttpModule, becayse HttpModules handle all traffic on an application.  So, if you just remember this fundamental difference in purpose between the two, then shouldn't have my problems in the future.

Simplified Universal HttpHandlerFactory Technique

A few months ago I wrote about the Universal HttpHandlerFactory Technique where you have one HttpHandlerFactory that all your ASP.NET processing goes through and then in that HttpHandlerFactory you then choose what HttpHandler is returned based upon what directory or file is accessed.  I still like this approach for certain scenarios, but my blog got to the point where I was managing 11 different HttpHandlers for about 25 different path and file patterns.  So, it was time to simplify.

What I came up with was basically my go to card for everything: put it in SQL Server.  From there I just checked the URL being accessed against the patterns in a database table and then looked up what HttpHandler to use for that particular request.  Then, of course, I cached the HttpHandler for future file access.

Here are my SQL Server tables (yes, I do all my design in T-SQL-- SQL GUI tricks are for kids):

create table dbo.HttpHandlerMatchType  (
HttpHandlerMatchTypeId int primary key identity not null,
HttpHandlerMatchTypeName varchar(200) not null
) 

insert HttpHandlerMatchType select 'Contains'
insert HttpHandlerMatchType select 'Starts With'
insert HttpHandlerMatchType select 'Ends With'
insert HttpHandlerMatchType select 'Default'

create table dbo.HttpHandler (
HttpHandlerId int primary key identity not null,
HttpHandlerMatchTypeId int foreign key references HttpHandlerMatchType(HttpHandlerMatchTypeId),
HttpHandlerName varchar(300),
HttpHandlerMatchText varchar(200)
) 

Here is the data in the HttpHandler table:

 HttpHandler Table

Looking at this image and the SQL Server code, you can see that I'm matching the URL in different ways.  Sometimes I want to use a certain HttpHandler if the URL simply contains the text in the HttpHandlerMatchText and other times I'll want to see if it the URL ends with it.  I included an option for "starts with" as well, which I may use in the future.  This will allow me to have better control of how paths and files are processed.  Also, notice that one is "base".  This is a special one that basically means that the following HttpHandler will be used (keep in mind we are in a class that inherits from the PageHandlerFactory class-- please see my original blog entry):

base.GetHandler(context, requestType, url, pathTranslated);

Now in my HttpHandlerFactory's GetHandler method I'm doing something like this (also note how LLBLGen Pro helps me simply my database access):

HttpHandlerCollection hc = new HttpHandlerCollection( );
hc.GetMulti(new PredicateExpression(HttpHandlerFields.HttpHandlerMatchTypeId != 4));

IHttpHandler hh = null;
foreach (HttpHandlerEntity h in hc) {
    hh = MatchHttpHandler(absoluteUrl, h.HttpHandlerName.ToLower( ), h.HttpHandlerMatchTypeId, h.HttpHandlerMatchText.ToLower( ));
    if (hh != null) {
        break;
    }
}

This is basically just going to look through all the HttpHandlers in the table which are not the "default" handler (which will be used when there is no match).  The MatchHttpHandler method basically just passes the buck to another method depending of whether I'm matching the URL based on Contains, StartsWith, or EndsWith.

private IHttpHandler MatchHttpHandler(String url, String name, Int32 typeId, String text) {
    IHttpHandler h = null;
    switch (typeId) {
        case 1:
            h = MatchContains(url, name, text);
            break;

        case 2:
            h = MatchStartsWith(url, name, text);
            break;

        case 3:
            h = MatchEndsWith(url, name, text);
            break;

        default:
            throw new ArgumentOutOfRangeException("Invalid HttpHandlerTypeId");
    }

    return h;
}

Here is an example of one of these methods; the others are similiar:

private IHttpHandler MatchContains(String url, String name, String text) {
    if (url.Contains(text)) {
        return GetHttpHandler(name);
    }
    return null;
}

As you can see, it's nothing fancy.  The last method in the chain is the GetHttpHandler, which is basically a factory method that converts text into an HttpHandler object:

private IHttpHandler GetHttpHandler(String text) {
    switch (text) {
        case "base":
            return new MinimaBaseHttpHandler( );

        case "defaulthttphandler":
            return new DefaultHttpHandler( );

        case "minimaapihttphandler":
            return new MinimaApiHttpHandler( );

        case "minimafeedhttphandler":
            return new MinimaFeedHttpHandler( );

        case "minimafileprocessorhttphandler":
            return new MinimaFileProcessorHttpHandler( );

        case "minimapingbackhttphandler":
            return new MinimaPingbackHttpHandler( );

        case "minimasitemaphttphandler":
            return new MinimaSiteMapHttpHandler( );

        case "minimatrackbackhttphandler":
            return new MinimaTrackBackHttpHandler( );

        case "minimaurlprocessinghttphandler":
            return new MinimaUrlProcessingHttpHandler( );

        case "projectsyntaxhighlighterhttphandler":
            return new ProjectSyntaxHighlighterHttpHandler( );

        case "xmlrpcapi":
            return new XmlRpcApi( );

        default:
            throw new ArgumentOutOfRangeException("Unknown HttpHandler in HttpHandlerMatchText");
    }
}

There is one thing in this that stands out:

case "base":
    return new MinimaBaseHttpHandler( );

If the "base" is simply a call to base.GetHandler, then why am I doing this?  Honestly, I just didn't want to pass around all the required parameters for that method call.  So, to make things a bit more elegant I created a blank HttpHandler called MinimaBaseHttpHandler that did absolutely nothing.  After the original iteration through the HttpHandlerCollection is finished, I then do the following (it's just a trick to the logic more consistent):

if (hh is MinimaBaseHttpHandler) {
    return base.GetHandler(context, requestType, url, pathTranslated);
}
else if(hh != null){
    if (!handlerCache.ContainsKey(absoluteUrl)) {
        handlerCache.Add(absoluteUrl, hh);
    }
    return hh;
}

One thing I would like to mention is something that that sample alludes to: I'm not constantly having everything run through this process, but I am caching the URL to HttpHandler mappings.  To accomplish this, I simply setup a simple cached dictionary to map URLs to their appropriate HttpHandlers:

static Dictionary<String, IHttpHandler> handlerCache = new Dictionary<String, IHttpHandler>( );

Before ANY of the above happens, I check to see if the URL to HttpHandler mapping exists and if it does, then return it:

if (handlerCache.ContainsKey(absoluteUrl)) {
    return handlerCache[absoluteUrl];
}

This way, URLs can be processed without having to touch the database (of course ASP.NET caching helps with performance as well).

Related Links

All my work in this area has been rolled-up into my Themelia ASP.NET Framework, which is freely available on CodePlex. See that for another example of this technique.

Minima, DFF, and SolutionTemplate/E-Book now in Subversion

I've recently realized how lame it is to have to download a new ZIP file each file a new version of a framework is released or when a project has some changes. So, I'm moving my projects to Subversion instead of making everyone download my ZIP files. This should help me update the projects more often and allow everyone else to get my projects easier. Please note that this replaces all RAR/ZIP files I've previously released.

Currently, I have the following projects in Subversion:

  • Minima
  • Data Feed Framework
  • NetFXHarmonics .NET SolutionTemplate With E-Book

You can access these projects with any Subversion client, though you would probably want to use TortoiseSVN for Windows development. You can access the projects at the following SVN HTTP addresses. You are free to also use these SVN HTTP locations to browse through the code in your web browser. My primary emphasis is in .NET training and education, so I do hope this helps. Also, given that my SolutionTemplate is also my e-book, you can easily look at the files there and read them online without having to download the project.

Note the /trunk/ path at the end. There are currently no projects in the tags section of the Subversion repository and, honestly, I'm still planning what to do with that section. The branches section is currently set to not allow anonymous access.

By the way, if you're unfamiliar with it, Subversion is an incredibly powerful and seamlessly easy to use revision control system that allows for code repositories (that is, code stores) to be stored in a centralized local to allow access from diverse locations. Subversion also does automatic versioning of your commits (that is, saves) to the code repository. Not just versioning as in a magic number change, but also as in it saves all versions of your files so you can go back and see your changes over time.

Subversion is used for many different reasons and some of them have nothing to do with code. For example, I've been using something similar to it (CVS) for a rather long time now to store all my documents so I can keep everything stored in a centralized location and so I can see the progress of my work. One use that I found rather interesting was that one company was using Subversion to store and provision new instances of their application. So, you can use it as a place to store your code, as a global file system, or as an application repository. Subversion stores whatever you want to store, including binary files. For more information on Subversion, see the online O'Reilly e-book "Version Control with Subversion" below.

Related Links

NetFXHarmonics SolutionTemplate/E-Book

Recently I started putting together my standard .NET solution template for public release. This template contains the base architecture and functionality that all my projects need. This template is also organized in a very clear way that clearly separates each type of element into it's own section to maximize expansion and ease of development.

In order to make sure that the solution is understandable by many different types of developers, there are commentaries in each file in the solution. In addition to this, many of the files have full chapter-length lessons on a development topic contained in that file. For example, in the Code/SampleDomManipulator.js file, I wrote a rather extensive introduction to JavaScript browser dynamics through DOM manipulation. Because of these lessons, this solution template is also living .NET e-book.

Here is a list of some of the topics I've written about in this first release of my solution template, some of them are simple explanations and others are lengthy detailed lessons.

  • HttpHandler Creation
  • HttpModule Creation
  • HttpHandlerFactory Creation
  •  
  • Custom Config Section Creation
  • .NET Tracing
  •  
  • MasterPages Concepts
  • Global.asax Usage
  •  
  • CSS Theming, Management, and Media-Specific Sheets
  •  
  • JavaScript Namespaces
  • JavaScript File Consolidation
  • Firefox Console Usage
  • JavaScript Anonymous functions
  • JavaScript Multicast Event Handling
  • DOM Element Creation
  • DOM Element Manipulation
  • DOM Element Deletion
  • JavaScript Event Handling with Low Coupling
  •  
  • JavaScript GET/POST XmlHttp Service Interop
  • Manual XmlHttp Service Creation
  •  
  • JavaScript/CSS/ASP.NET/C# Code Separation
  • Highly Cohesive Type Organization

This solution template could be used for the basis for production projects or as a training utility for people new to ASP.NET, people new to JavaScript, DOM Manipulation or AJAX or people who just want to learn how to organize their projects more effectively.

As with all my projects, but much more so with this one, I will be updating the solution template over time to account for more AJAX techniques and .NET technologies. I will also continue to expand the commentaries and lessons to the point where this solution itself becomes a case study, a sample application, and book all wrapped up in one.

Links

1 2 3 4

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

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