Wednesday, August 26, 2009

Creating Modal Windows with Coolite

One of the most popular effects in web development, is the modal dialog.  Using standard CSS we are able to create the appearance of a modal dialog on a webpage that can be used to provide a quick login form, more information, or any of a thousand other things.  Naturally, most UI frameworks have this effect built-in so developers can quickly create this effect without having to worry about cross browser problems; Coolite is no exception.

Generally, the way this is achieved is a <div> is placed somewhere on the page (usually at the bottom) and is targeted with JavaScript which does some fanciness to give it various look-and-feel properties.  Coolite is slightly different, but in a way that makes more sense.  It leverages the idea of the “viewport” as the main page, that is what the user see’s without the modal.  In Coolite we would define this as such:

<ext:ViewPort ID="vp1" runat="server" AutoHeight="true">
    <Body>
    </Body>
</ext:ViewPort>

The basic idea here is that the viewport serves as a wrapper for your main content.  So we could define our main UI here, for this example we will simple put a button which opens the modal.

<ext:ViewPort ID="vp1" runat="server" AutoHeight="true">
    <Body>
        <ext:Button ID="btnOpen" runat="server" Text="Open"
            Icon="Application">
            <Listeners>
            </Listeners>
        </ext:Button>
    </Body>
</ext:ViewPort>

Next we define the code for our Modal window, for this example, we are going to constrain the width and put some lipsum text

<ext:Window ID="Window1" runat="server" AutoHeight="true" Width="400" Constrain="true"
    Modal="true" ShowOnLoad="false" ButtonAlign="Right" Title="Modal Window">
    <Body>
        Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum
        has been the industry's standard dummy text ever since the 1500s, when an unknown printer
        took a galley of type and scrambled it to make a type specimen book. It has survived not
        only five centuries, but also the leap into electronic typesetting, remaining essentially
    </Body>
    <Buttons>
        <ext:Button ID="btnClose" runat="server" Text="Close" Icon="Cancel" />
    </Buttons>
</ext:Window>

So this is fairly simple and straightforward.  We have defined our main layout in a ViewPort and then we have defined external layout elements (the modal) in Windows that are defined outside the ViewPort.  I defined only the essential properties of the modal, but there are quite a few properties, such as X and Y to define the starting location of the modal.

However, we are missing one critical element; with this current code there is no way to show the modal to the user.  There are two ways to do this, and your selection of the means to do this will depend on your scenario.  You can open this with both JavaScript and the .NET code behind.  In JavaScript, we simply add a listener node and listen for the “Click” event.  Thus our buttons definition looks like this:

<ext:Button ID="btnOpen" runat="server" Text="Open"
    Icon="Application">
    <Listeners>
        <Click Handler="Window1.show();" />
    </Listeners>
</ext:Button>

This is the approach I like to take for simple calls, just define the Handler property with the JavaScript you want.  Its a “do it once and throw it away'”.  However, if you’re going to duplicate logic and call it throughout the page, I would then define the Fn property and centralize all that logic in a single function.

In addition, the Window component has many events that you can catch, with JavaScript or Server-side code, though client side will be much easier to understand.  I will list out some of the more useful ones that I have used:

  • BeforeShow – fires just before the modal is shown to the user.  Useful as a means of resetting modal content from an pre-existing operation.
  • BeforeHide – fires just before the modal disappears from the users view
  • Hide – fires after the modal is closed via a call to hide() on the Window element
  • Show – fires after the modal is shown to the user

So as I mentioned the same effect can be accomplished using AjaxEvents.  To do this you would simply update the Button definition removing the <Listeners> node with the <AjaxEvents> note, like such:

<ext:Button ID="btnOpen" runat="server" Text="Open"
    Icon="Application">
    <AjaxEvents>
        <Click OnEvent="btnOpen_Click">
            <EventMask ShowMask="true"
                Msg="This is a Loading Mask" />
        </Click>
    </AjaxEvents>
</ext:Button>

This defines that for the button the Click event raises an AjaxEvent which is handled by the btnOpen_Click method in the page code behind.  From this position you have access to related page elements.  What does it mean to be related?  I honestly dont know, this is one of the aspects of Coolite that is largely undocumented.  From what I can gather, it seems to be the parent container, though you can define a specific form to link to the AjaxEvent, via the FormID attribute.

Notice that we are also defining a mask to be visible when this event is occurring.  Remember that we are going back to the server, so it makes sense to give the user some feedback; thus in the event the operation takes time the user is notified and appropriate interactions can be prevented.  To give you an idea what the code behind method looks like in this case, here is what btnOpen_Click looks like:

protected void btnOpen_Click(object sender, EventArgs ev)
{
    Window1.Show();
}

Very simple and straightforward.  You could imagine having checks in here to prevent the modal from showing if certain conditions were not met, or populating modal elements with server data.

To conclude, the big thing to remember about Coolite modals, is that they must be placed outside a ViewPort component with the Modal property set to true.  There a wide variety of properties that you can configure for the window to improve the look and feel of the modal as well as positioning.  Modals provide a great way to display related information or provide a drill down into data, they can be used to simplify interfaces and provide more elegant ways to access commonly used functionality, while continuing to move the web application closer to the goal of behaving like a desktop application.

Monday, August 24, 2009

Understanding AjaxEvents in Coolite ASP .NET

In the first tutorial in this series we created a very basic Hello form that relied on JavaScript for its core.  We also saw how easy it was to build a very clean and modern looking form using Coolite.  But what are there things called AjaxEvents.

Going to the Coolite website we find that, as with most of Coolite, there is a total lack of documentation as to what AjaxEvents are, although there are samples showing how to use them.  Based on these examples I would say they are simple postback requests that can be used to post data to the server.

They are able to “target” a specific form (they default to the form they are in) and send the current state of the items in that form to the ASP .NET code behind where they can be operated on as desired.  These requests are then able to fire the events of other controls that have events defined (ex Grid, Store). In addition, you are able to configure an event mask for while the request is in process. This helps the user know that “something is happening”.

So to begin here is a screenshot of code from the first tutorial, but I have cut the JavaScript out and removed the Listeners node from the Button
image

The first step is to update the Button markup as such:

<Buttons>
  <ext:Button ID="btnSubmit" runat="server"
   Text="Submit" Icon="Accept">
    <AjaxEvents>
      <Click OnEvent="btnSubmit_Click">
      </Click>
    </AjaxEvents>
  </ext:Button>
</Buttons>

Very similar to the <Listeners> node (and in fact these can be combined with a listener, return false, will stop the request), we are saying that “when the Click event occurs, create an AjaxEvent which is handled by the handler btnSubmit_Click in the code behind”.  This what our handler could look like:

protected void btnSubmit_Click(object sender,
     AjaxEventArgs ev)
{
     Ext.Msg.Alert("Alert",
         string.Format("Hello {0}", txtName.Text)
     ).Show();
}

Notice that we are using the AjaxEventArgs type for the EventArgs type. This is a special event args that contains a few extra properties that can be of use. Most notably the ExtraParam and ExtraParamnsResponse properties. The former allows you to send this via the Ajax call that may not be contained in controls you can access.

The final piece of this application is the event mask. This is a very simple operation so we dont really need a mask. Masks are very useful to for stopping the user from interacting with the page or parts of the page while an action is in progress. With Coolite these are easily definable and fit well with the application.

First add a call to “Thread.Sleep(1000);” to you handler function so that you will get a chance to see the mask we are doing to define. Return to the Button code and update it as such:

<ext:Button ID="btnSubmit" runat="server"
    Text="Submit" Icon="Accept">
    <AjaxEvents>
        <Click OnEvent="btnSubmit_Click">
            <EventMask Msg="Generating Message" ShowMask="true"
                Target="CustomTarget" CustomTarget="fp1" />
        </Click>
    </AjaxEvents>
</ext:Button>

The two key properties in the <EventMask> tag are ShowMask and Msg.  The former states that when this event is active we do want to show the mask.  The later defines what message the user will see while the event is in progress.  In addition, I have defined the Target as CustomTarget which allows me to specify which section will be grayed out, by default it is the entire page.  In this case I am specifying the control with the ID of “fp1” which is the FormPanel all of this is sitting inside of.  The end result is when you are waiting for the name to come back, your form should look like this:
image

To conclude, this article focused on using AjaxEvents with Buttons and how to control the EventMask.  Remember that you can do a lot more with AjaxEvents as they can be applied to most any control.  You just need to tweak things sometimes and always check your pages that the calls are getting the right state data from the controls.  Most of my testing has been with FormPanels and I have found that things not inside FormLayouts are often not submitted for whatever reason.

AjaxEvents are a big reason why I enjoy using Coolite with webforms over MVC; because I can take advantage of events are server side code in C# as opposed to writing more JavaScript.  But using these two posts you should understand that your code will not be that different in most cases, regardless of which approach you use.

Sunday, August 23, 2009

Getting Started with Coolite on ASP .NET

I am currently engaged in an opportunity that has taken me to New York to help a client rewrite one of their existing VB6 applications in ASP .NET as a web application.  To aid us with developing this application and provide a very modern and consistent look and feel we are using the Coolite UI Framework for ASP .NET which leverages the powerful ExtJS JavaScript library inside of WebForm controls.

However, we have found that the the biggest downside to using Coolite is the intense lack of documentation from the creators. This makes it hard to know exactly what we are doing and often leaves us to pull from two or three sites to fully understand what it is capable of.  The biggest help comes from the Examples site, and the ExtJS documentation site, since the controls follow the supported properties for those controls. ExtJS has excellent documentation.  But I wanted to talk about Coolite cause I think it has a lot of potential and can really be very helpful if people learn more about it.  So to start this series I am going to give a very basic example of an application which uses Coolite and JavaScript.  So lets get started.

To begin you will need to download the Coolite binaries from Coolite.com, this will install three binaries (Coolite.Ext.Web.dll, Coolite.Utilities.dll, and Newtonsoft.Json.dll) and reference these in your solution.

The second step is to update your web application web.config file to support Coolite in the application.  So first add this line to your web.config after the last section group.

<configSections ..>
  </sectionGroup>
  <section name="coolite"
       type="Coolite.Ext.Web.GlobalConfig"
       requirePermission="false"/>
</configSections>
<coolite idMode="Explicit"
       theme="Default"
       initScriptMode="Linked"
       scriptMode="Debug" />

Also included in this screen shot is the next step of what to add, and that is the new section as defined by the section definition we just added.  Here you can specify a number of things, but the two things to take note of here are:

  • idMode:  use Explicit here so that Coolite controls can be referenced in JavaScript without worry about naming containers as with typical ASP .NET controls
  • theme: defines the UI styles that Coolite will reference for all controls. Can be Default, Gray, Slate

The next thing we have to add are some reference to HTTP handlers and modules; so we add the following lines to the web.config:

To httpHandlers:

<httpHandlers>
  <add path="*/coolite.axd" verb="*"
     type="Coolite.Ext.Web.ResourceManager"
     validate="false"/>
</httpHandlers>

To httpModules:

<httpModules>
    <add name="AjaxRequestModule"
         type="Coolite.Ext.Web.AjaxRequestModule,
                    Coolite.Ext.Web"/>
</httpModules>

Optionally, I like to add the following line to my pages collection in system.web to make referencing the Coolite controls easier:

<pages>
    <controls>
        <add assembly="Coolite.Ext.Web"
            namespace="Coolite.Ext.Web"
            tagPrefix="ext"/>
    </controls>
</pages>

So lets start with building a simple form that will say “Hello {name}” provided a name in a textbox.  I am going to do this using JavaScript on the client side, another blog post will detail doing it with AjaxEvents.

So lets first show some basic markup that uses Coolite to create a form, this first thing that every page using Coolite controls must have is a ScriptManager to facilitate the inclusion of JavaScript to support the various effects, so:
image

Next, we will want to create a small form, so we will use a FormPanel control, which gives us a very nice look and feel, so:
image

I have defined a lot of properties on the form, here is an explanation for a few of them:

  • FormID: Used in AjaxEvent referencing and to tie controls to certain actions, not really used in this approach, but will be useful when we show AjaxEvents
  • Title: The title displayed for the Form (see next screenshot)
  • ButtonAlign: The alignment of the buttons defined in the FormPanels <Buttons> portion
  • StyleSpec: The style rule to apply to the panel as a whole

Running this should produce the following UI:
image

Not a bad looking UI considering we haven’t had to do any CSS and this is compatible with IE6 even, so lets keep moving forward and add the actual UI.

The FormPanel has quite a few internal sections, for this tutorial we will use two of them <Body> and <Buttons>.  Here is the updated code:

   1:  <body>
   2:    <ext:ScriptManager ID="ScriptManager1" runat="server" />
   3:    <ext:FormPanel ID="fp1" runat="server"
   4:      FormID="mainForm" Title="Test Form"
   5:      Height="150" Width="300" ButtonAlign="Right"
   6:      BodyStyle="padding: 10px;" 
   7:      StyleSpec="margin: 10px;">
   8:      <Body>
   9:        <ext:FormLayout ID="frmLayout" runat="server"
  10:          LabelSeparator=" " LabelAlign="Left">
  11:          <ext:Anchor>
  12:            <ext:TextField ID="txtName" runat="server"
  13:              AllowBlank="false"
  14:              MaxLength="15" FieldLabel="Name" />
  15:          </ext:Anchor>
  16:        </ext:FormLayout>
  17:      </Body>
  18:      <Buttons>
  19:        <ext:Button ID="btnSubmit" runat="server" Text="Submit" Icon="Accept" />
  20:      </Buttons>
  21:    </ext:FormPanel>
  22:  </body>

So what we have done first is the update the body of the FormPanel with a FormLayout.  There are a lot of things that FormLayout does for us, but for new its enough that it will render the elements described in each <ext:Anchor> block vertically with some label text to the left.

In this case we are adding a a Ext Textfield that has a few things defined:

  • AllowBlank – the textbox will validate user input and require input
  • FieldLabel – this is the text of the label that will appear to the left. It can also appear above the control, this controlled by the LabelAlign property (see the FormLayout)

Next we move to the <Buttons> group. This section is placed beneath the Panel body and houses button controls, here I am defining a single button.  If you run this, it should output something like this:
image

The next part of this is to allow the user to click “Submit” and have the program respond with an Ext alert that says “Hello”.  So the first thing we will need is something to listen for this event.  Update the Button definitions as such:

<ext:Button ID="btnSubmit" runat="server"
  Text="Submit" Icon="Accept">
  <Listeners>
    <Click Fn="SayHello" />
  </Listeners>
</ext:Button>

There are a number of events that we can listen for, obviously the one that makes the most sense in this case is Click.  So when a click happens we want to call the function SayHello. So here is a look at the SayHello function:

<script language="javascript" type="text/javascript">
    var SayHello = function() {
        var name = txtName.getValue();
        Ext.Msg.alert("Alert", "Hello " + name);
      }
    </script>

Notice how we are getting the value of the text field, we are simply calling its name, no ClientID (in this case).  We are then creating an ExtJS alert window to display the message.  The reason we use this here is that it will provide an alert that is linked to our theme, this way all visual elements have the same appearance.  So clicking the button should do this:
image

One thing I do want to point out is that this alert window is NOT an alert window.  It does not block execution, it relies on callbacks to execute code after the “OK” click.  It is nothing more than a modal dialog being shown.

So there you have it, that is a very basic application which uses Coolite to perform a very basic function.  The next time around we will describe how to do this using AjaxEvents, which are a very interesting concept and take much of the problems you encounter with MS Ajax out of the picture.

Saturday, August 15, 2009

Moving from ASP .NET MVC to ASP .NET Webforms

It is very common to hear developers talk about successfully switching to MVC and generating much cleaner applications and there is no doubt that using MVC can certainly generate that.  But as with any technology/framework, misusing it can still result in an application with maintainability issues and the need for the developer to make undesirable decisions.

Such was the case out here in New York where our client had decided to use the MVC framework with the Coolite UI toolset. I am a big believer then when it comes to using the MVC framework one needs to be careful that the toolset you are using also leverages what MVC gives you.  In the case of the project out here, after numerous discussions it was clear that really the way we were approaching the project we were just not going to leverage MVC in a way that would make sense to use it.  In reality, the project would be better off, given the aims, as a Silverlight project, but due to circumstances surrounding the project it was not an option.

In addition, we had decided to use the Coolite control toolkit for UI.  Given the way that Coolite is setup it makes sense to use it with WebForms over MVC.  While you can certainly use MVC with Coolite (as demonstrated by http://mvc.coolite.com) after spending a week developing in MVC with Coolite it became apparent that it didn’t make sense and I felt we were heading for some problems.  I took these problems to the other developers and after some conversation we decided we needed to talk to the client about possibly changing, let me enumerate some of the arguments that were made:

  • MVC’s biggest strength is the decoupling of the view from the controller and the lack of reliance on server controls
    • In our case we are not really using this methodology heavily, instead relying more on web services to talk to the database. This due to the other devices that must be able to tie into this system
  • Coolite is designed to work with ASP .NET webforms.  Using Coolite with MVC means a large reliance on JavaScript to gather values and perform saves.
    • Using Webforms we can use the code behind to leverage .NET in a way that makes sense given the operations we are performing
  • With Webforms we can still use web service method calls to get data from our database.  It also allows use to make WCF calls via code-behind if needed

The big point that was made here was that we are only talking minimal gain using MVC from a structure standpoint vs. potentially difficult choices in saving and persisting data and leaning very heavily on JavaScript.  In addition, if done properly an ASP .NET Webform app can be just as well organized as an MVC application if done correctly.  I have certainly see it done by some of the best in the industry and I have their experience to lean on in doing this.  I really think this is the best decision, as much as I want to use MVC, I think you just don't gain anything give what we are doing and how we are approaching it.

Saturday, August 01, 2009

Repository Pattern (Revisted)

In the previous tutorial set we looked at the Repository pattern and how one might use it to construct a support framework for Fluent NHibernate.  If you looked at closely you likely realized some very serious and obvious design flaws.  The main thing that I didn't like about it was the use of the derived repositories and the constraints it placed on various user stories.  For example, in order to save related items, or perform read operations, multiple repository instances were needed.  This creates a huge burden on the developer.  What is really needed in this case is a store, that is a single class that provides lazy loaded instances of the other repositories the system supports.

To begin this process, we first need to generate code.  Our types are not known to use at any point until after a database is read.  To do this we will use T4 templates.  I will blog later on about creating these templates for now we are just working to understand the theory.

So the idea behind this reorganization is to create a single class that all other repositories work off.  The repository instances for the specific models will need to provide enough extensibility to let developers take control of the save process, but also provide enough out of the box functionality so that it is useful without modification.

Furthermore, we want to encourage developers to use our single instance so we need to provide a way for their functions to be called in place of our original.  To do this we will use abstract base classes with virtual methods.  By defining a default save method as virtual in the base class we can provide the developer a way to override the function that is automatically called when a Commit is initiated on the store’s objects.

So the Store is generally in charge of initiating the Commit process via reflection and finding appropriately decorated properties that represent the Repositories.  The commit is only called if the list is deemed to be dirty.

Each of the derived repositories can only hold objects of certain type, the type must inherit from EntityBase thereby insuring that the object being operated on is an Entity.  Finally the Entity saving, deleting, and updating operations are all handled in a totally database agnostic way by NHibernate under the hood thanks to the mapping generated via Fluent NHibernate.

So the end result of this process is that using T4 templates we are able to generate the POCO (Plain Old C# Objects) model files, the Fluent Mapping files, the Derived Repository definitions and the generated portion of the Store all automatically.  In addition, we make all classes partial enabling developers to extend them as they see fit.  This gives us a tremendous about of flexibility for developers to customize certain operations.  This model for repository is a little more closer to what the pattern fully intends, though really is more of a Store pattern, similar to what Linq to SQL and Linq to Entities appear to use to great effect.  In coming tutorials I will back track and help you understand how to create a fully functional Repository Store support framework.