Aug 27 2007

Extending Iron Speed: Blowery Compression

Category: Iron Speed, Programminglomaxx @ 11:52 am

Iron Speed Designer is a great tool for rapid application development, however the web interfaces it builds can be a little cumbersome at times. Recently I decided to see if I could implement blowery compression to see if I could improve performance. Below is a guide to outline the steps I took to enable blowery for an Iron Speed application.

Setting Up Blowery

Blowery setup was pretty easy. All I had to do was download the binaries, extract them and copy the following dll’s over to my applications bin folder:

blowery.Web.HttpCompress.dll
ICSharpCode.SharpZipLib.dll

Once I’d copied these files over to my bin directory I modified my web.config file to include the following sections:

In the Configuration section, I added the following configSection:

<sectionGroup name="blowery.web">
      <section name="httpCompress" type="blowery.Web.HttpCompress.SectionHandler, blowery.Web.HttpCompress"/>
</sectionGroup>

And in then added the following section directly under my appSettings as per the installation instructions

<blowery.web>
    <httpCompress preferredAlgorithm="gzip" compressionLevel="high">
      <excludedMimeTypes>
        <add type="image/jpeg"/>
        <add type="image/gif"/>
      </excludedMimeTypes>
      <excludedPaths>
        <add path="NoCompress.aspx"/>
      </excludedPaths>
    </httpCompress>
  </blowery.web>

I also added this to the HttpHandlers section:

<add verb="GET" path="ScriptResource.axd" type="Microsoft.Web.Handlers.ScriptResourceHandler" validate="false"/>

And finally added the following to my HttpModules section:

<add name="CompressionModule" type="blowery.Web.HttpCompress.HttpModule, blowery.web.HttpCompress"/>

Small bug with scriptresource.axd

Once I had installed the compression module, I was getting some javascript errors which were related to ScriptResource.axd. To fix this I added it to the excludedPaths section the blowery.web config section

<<blowery.web>
    <httpCompress preferredAlgorithm="gzip" compressionLevel="high">
      <excludedMimeTypes>
        <add type="image/jpeg"/>
       <add type="image/gif"/>
      </excludedMimeTypes>
      <excludedPaths>
        <add path="NoCompress.aspx"/>
        <add path="ScriptResource.axd"/><!--just to be sure-->      </excludedPaths>
    </httpCompress>
  </blowery.web>

Once I’d completed that, I saved the config file and blowery compression was enabled for my Iron Speed application.


Aug 23 2007

Tafiti Search Engine

Category: Programminglomaxx @ 10:51 pm

So I tried out the Tafiti beta today and I have to say, while it looks pretty enough, it’s still very much Beta software.

Here are some of the features:

There’s this little icon tray which will show relevant results depending on which icon you click. I guess it’s cool in theory, but one thing I found annoying was that it split blog posts up from regular content which is annoying, especially for developers as a lot of the good stuff is in peoples blogs so it creates an extra click for me to see a set of relevant search results.

To the right of the search results, they have a “Glass Shelf” where you can store and tag relevant results. This is pretty neat, especially for saving extra search results that you might want to investigate later. Also you can click on each shelf and either email or blog about the post

You can also apply tags to each shelf which allows you to store a stack of items on the shelf which I think is a pretty nice touch.

Aside from dragging individual results to a shelf, you can also drag a whole search to a shelf and stack those so you can keep your favourite searches.

On the left hand side, it will also stack your searches from the current session so you can easily go back to them which is handy, because the system is built on silverlight which, like flash, doesn’t cope with clicking the back button.

In the top right of the screen you can also filter the current search results to get more relevant content for your search. I think this is a really neat inclusion and is something that I actually would have to say, I’d like to see in google.

A couple of things that annoyed me were the fact that the scroll button on my mouse didn’t work with the search results and it also cuts off the text on the results displayed on my laptop.

Apart from that and considering it is very new technology, I have to say that unlike a lot of the other search products popping up, this one has a fair bit of potential.


Aug 23 2007

Integrated Version Control With Visual Studio

Category: Programminglomaxx @ 1:39 pm

Subversion is a great version control system and has many many advantages, however one of the things that people don’t often consider an advantage is the fact that it isn’t integrated into the development IDE. Many people actually consider this to be a disadvantage and I’ve actually talked to people who don’t want to use subversion because there isn’t really a gui for it that integrates nicely with the development IDE, but if I could go back and talk to those people now, I’d spend more than a minute or two telling them I disagree.

Most people when they start working at a new company spend a bit of time adjusting to the way they do things. Sometimes these adjustments are easy, sometimes they’re hard at first, but become second nature after a week, and sometimes no matter how long you’ve worked there, you just can’t get used to the way people do things.

About a year ago the company I worked for decided that our previous source control system, Visual Source Safe wasn’t up to scratch and so we decided to migrate across to subversion. I had heard a lot about the power of subversion, but probably the biggest concern I had was that the gui that we were going to use (TortoiseSVN) didn’t integrate with the Visual Studio IDE. I had pretty much submitted myself to the fact that this was going to be a case of no matter how long I worked with it, I wasn’t going to like having to use a separate tool to manage my source control. In my mind I was convinced it was a step backwards.

Well 12 months on, and I must say that not only have I gotten used to working with TortoiseSVN as a separate tool, I no longer want my source control client integrated with my development environment under any circumstances. In fact, another source control product I use is SourceGear Vault which is a great source control tool and it does integrate with Visual Studio, but since I’ve been using TortoiseSVN, I’ve abandoned Vault’s integration and gone back to using the client.

There are a number of reasons why I prefer the non-integrated approach:

  1. It Works
    I’ve used VSS for a few years now, and most often it has been integrated with Visual Studio. The problem I’ve found with this is that whilst Visual Studio was pretty stable and whilst the Source Safe client rarely crashed, as soon as you merged the two together, they just couldn’t work out a way to co-exist. Files would get locked, IDE’s would shut down for no particular reason and don’t even think about moving your files around. Those VSS bindings weren’t called bindings for nothing.
    I have to admit, Vault was an improvement but it still crashed regularly enough for me to notice.
    Since I’ve gone the non-integrated road, my source control client never crashes and my instances of Visual Studio are also a lot more stable.
  2. Non-Intrusive Start Up
    Before I ditched my integrated source control solution, my projects and solutions that were in source control took an age to load. Not only that, there would be popup messages asking me to log in, or point to a repository or telling me that I was offline and get some inane message about whether or not I wanted to work offline. It all led to a very intrusive start up experience. All I wanted to do was start up visual studio and begin coding. What I didn’t want to do was answer a series of questions on how I wanted to work with source control. Now when I start up visual studio, it just starts and starts much quicker than it ever would have done with the integrated clients.
  3. I don’t have to be online
    One of the things I absolutely hated with VSS was that you had to be online to check out files. With Vault you don’t have to be, but it sure does complicate things if you’re offline. With subversion, because it’s not integrated, it doesn’t care if I’m offline or online, so I can fire up Visual Studio whenever I want to work on my code. When I need to do a commit I can do that when I get back online and life goes on.

I’m sure there are many other reasons why integrated source control is not as advantageous as it first seems, but these are the big ones for me and are a reason that I would never have any problems recommending to people that not only is it not a disadvantage, it’s in fact a very compelling advantage to move towards using subversion with your Visual Studio products.


Aug 23 2007

Creating an Ajax Repeater with ASP.NET 1.1

Category: Programminglomaxx @ 12:36 pm

Introduction

The purpose of this article is to demonstrate how to create a simple repeater that can be loaded and refreshed using the Ajax.NET Professional framework to avoid posting back to the server.

Setting up the project

If you are already using the Ajax.Net Professional framework, you don’t need perform any additional setup. If you are setting up a new project, ensure that you have downloaded the Ajax.Net Professional binaries from here and included a reference to the AjaxPro.dll.

You will also need to add the following to your web.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <httpHandlers>
      <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/>
    </httpHandlers>
  [...]
  </system.web>
</configuration>

Step 1. Create a simple class to bind to the repeater

The first thing I need to do is create a simple object that I will populate with data. I will then create an arraylist of these objects, which will then become the datasource for my repeater which I will then be bound to the repeater via the Ajax Call.

Here is the simple class that I will use for this example:

Public Class PersonInfo
    Private _strFirstName As String
    Private _strLastName As String
    Private _dtDateOfBirth As Date
    Private _strState As String
    Public Property strFirstName() As String
        Get
            Return Me._strFirstName
        End Get
        Set(ByVal Value As String)
            Me._strFirstName = Value
        End Set
    End Property
    Public Property strLastName() As String
        Get
            Return Me._strLastName
        End Get
        Set(ByVal Value As String)
            Me._strLastName = Value
        End Set
    End Property
    Public Property dtDateOfBirth() As Date
        Get
            Return Me._dtDateOfBirth
        End Get
        Set(ByVal Value As Date)
            Me._dtDateOfBirth = Value
        End Set
    End Property

    Public Property strState() As String
        Get
            Return Me._strState
        End Get
        Set(ByVal Value As String)
            Me._strState = Value
        End Set
    End Property
End Class

 

As you can see it is a simple PersonInfo Class that has a number of public properties exposed.

Step 2. Create the Repeater

Create a new WebUserControl called ucRepeater.ascx in your project and drag and drop a new Repeater control onto the WebUserControl and rename it to “rptAjax” or some other meaningful name.

Switch to HTML view to modify the repeater. My repeater looks something like this:

<asp:Repeater id="rptAjax" runat="server">
    <ItemTemplate>
        <table>
            <tr>
                <td><strong>First Name:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "strFirstName") %></td>
            </tr>
            <tr>
                <td><strong>Last Name:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "strLastName") %></td>
            </tr>
            <tr>
                <td><strong>Date Of Birth:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "dtDateOfBirth") %></td>
            </tr>
            <tr>
                <td><strong>State:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "strState") %></td>
            </tr>
        </table>
    </ItemTemplate>
    <SeparatorTemplate>
        <br>
    </SeparatorTemplate>
    <AlternatingItemTemplate>
        <table bgcolor="#f5f5f5">
            <tr>
                <td><strong>First Name:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "strFirstName") %></td>
            </tr>
            <tr>
                <td><strong>Last Name:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "strLastName") %></td>
            </tr>
            <tr>
                <td><strong>Date Of Birth:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "dtDateOfBirth") %></td>
            </tr>
            <tr>
                <td><strong>State:</strong></td>
                <td><%# DataBinder.Eval(Container.DataItem, "strState") %></td>
            </tr>
        </table>
    </AlternatingItemTemplate>
</asp:Repeater>

Step 3. Create a BindRepeater Method

Now that I have a simple repeater and simple object that can be bound to the repeater, I need to build my collection to bind to the repeater.
To do this I’m going to create two simple methods in my WebUserControl. One to build my collection and the other to bind the collection to the repeater. They look like this:

'Basic method to build collections that will be bound to the repeater
    Public Sub BuildCollections()
        Me._objArray = New ArrayList
        Select Case Me._intState
            Case StatesEnum.NSW

                Dim BrettLee As New PersonInfo
                BrettLee.strFirstName = "Brett"
                BrettLee.strLastName = "Lee"
                BrettLee.strState = "NSW"
                BrettLee.dtDateOfBirth = "01/01/1977"
                Me._objArray.Add(BrettLee)
                Dim GlennMcgrath As New PersonInfo
                GlennMcgrath.strFirstName = "Glenn"
                GlennMcgrath.strLastName = "McGrath"
                GlennMcgrath.strState = "NSW"
                GlennMcgrath.dtDateOfBirth = "01/01/1974"
                Me._objArray.Add(GlennMcgrath)
                Dim MichaelClarke As New PersonInfo
                MichaelClarke.strFirstName = "Michael"
                MichaelClarke.strLastName = "Clarke"
                MichaelClarke.strState = "NSW"
                MichaelClarke.dtDateOfBirth = "01/01/1982"
                Me._objArray.Add(MichaelClarke)
            Case StatesEnum.VIC
                Me._objArray = New ArrayList
                Dim ShaneWarne As New PersonInfo
                ShaneWarne.strFirstName = "Shane"
                ShaneWarne.strLastName = "Warne"
                ShaneWarne.strState = "VIC"
                ShaneWarne.dtDateOfBirth = "01/01/1970"
                Me._objArray.Add(ShaneWarne)
                Dim BradHodge As New PersonInfo
                BradHodge.strFirstName = "Brad"
                BradHodge.strLastName = "Hodge"
                BradHodge.strState = "Vic"
                BradHodge.dtDateOfBirth = "01/01/1980"
                Me._objArray.Add(BradHodge)
        End Select
    End Sub
    'Method to bind collections to the repeater
    Public Sub BindRepeater()
        'This would normally be replaced with a call to the business layer to return your business objects.
        Me.BuildCollections()
        Me.rptAjax.DataSource = Me._objArray
        Me.rptAjax.DataBind()
    End Sub

 

As you can see all this code is a pretty standard affair. I also expose a public property intState that is used to keep track of the state that I want to select.

Now we’re going to start using some Ajax.

Step 4. Create a Webform

Next we need to create a new webform that will host the repeater and update it. My basic webform has a few key elements. The first is a Div that has an ID of “ContentDiv”. This div will act as a place holder to receive the response from my Ajax call.

So far my html page looks like this:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="AjaxRepeaterDemo.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
    <HEAD>
        <title>WebForm1</title>
        <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
        <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
        <meta name="vs_defaultClientScript" content="JavaScript">
        <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
    </HEAD>
    <body>
        <form id="Form1" method="post" runat="server">
            <div id="ContentDiv">
            </div>
        </form>
    </body>
</HTML>

In the codebehind I need to create a new function that will return the updated repeater contents. What happens here is that we need to create a new instance of the usercontrol that contains the repeater. We then need to bind it and finally render the output to a string which we can then pass back to the Ajax request.

The first thing we need to do is make sure we have marked the function with the <AjaxPro.AjaxMethod() > attribute. Once we have done that, we can write our function as normal.

'Set this attribute to enable ajax method.
    <AjaxPro.AjaxMethod()> _
    Public Function ChangeSelection(ByVal _intState As Integer) As String
        'Dynamically load an instance of the control
        Dim objUcRepeater As ucRepeater
        objUcRepeater = LoadControl("~/ucRepeater.ascx")
        'Bind the control
        objUcRepeater.intState = _intState
        objUcRepeater.BindRepeater()
        'Render the control output to a string
        Dim objStringBuilder As New System.Text.StringBuilder
        Dim objStringWriter As New System.IO.StringWriter(objStringBuilder)
        Dim objHtmlWriter As New HtmlTextWriter(objStringWriter)
        objUcRepeater.RenderControl(objHtmlWriter)
        'Return the output to the calling ajax method
        Return objStringBuilder.ToString
    End Function

As you can see, this function creates the control dynamically, binds the control then outputs it to a string by rendering the output to a htmlwriter.

The final thing we need to do in the code behind is register the page type for ajax in the Page_Load event. The way to do this is shown below:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AjaxPro.Utility.RegisterTypeForAjax(GetType(AjaxRepeaterDemo.WebForm1))
End Sub

Step 5. The Javascript

Once we have setup the basic webform and the codebehind we now need to setup the Javascript in the webform. We will also need a dropdown to update the repeater when a user selection changes.
We will then wire up calls to that function from both the body onload event and the dropdown to refresh the repeater once the dropdown selected index has changed.

Our body in the html section of our webform will now look like this:

<body onload='ChangeSelection();'>
        <form id="Form1" method="post" runat="server">
            <SELECT runat="server" id="ddlStateSelector" onchange='ChangeSelection();'>
                <OPTION selected value="1">NSW</OPTION>
                <OPTION value="2">VIC</OPTION>
            </SELECT>
            <div id="ContentDiv">
            </div>
        </form>
    </body>

As you can see, I have added a call to the javascript function ChangeSelection() in both the onload event of the body of the html and the onchange event of the dropdownlist.

Finally I need to write the javascript function that will look at my current selection in the dropdownlist and then update my ContentsDiv. This function is shown below.

<script type="text/javascript">
    function ChangeSelection()
    {
        var x = document.getElementById('ContentDiv');
        var ddlStateSelector = document.getElementById('ddlStateSelector')
        x.innerHTML = AjaxRepeaterDemo.WebForm1.ChangeSelection(ddlStateSelector.options[ddlStateSelector.selectedIndex].value).value;
    }
</script>

The final line in the function is the key here. This line makes the call to the server that binds then renders the repeater, and returns the output to the div.


Aug 04 2007

Enhancing Iron Speed: Using the AjaxControlToolKit ModalPopupExtender with Iron Speed Designer

Category: Iron Speed, Programminglomaxx @ 4:36 pm

This article will show you how to use the ModalPopupExtender from the AjaxControlToolKit in conjunction with an Iron Speed Designer generated application to insert a new record into a ShowTablePage using a Modal Popup Window. I’m going to assume that you are pretty familiar with Iron Speed and have already generated an application. What I will now do is extend a standard “ShowTablePage” to allow you to add records to the table by using a modal popup window.

Setup

Before we begin, you need to have a few things setup on your machine. I’ll assume you have Visual Studio already installed and that you also have the AjaxControlToolKit installed. If you don’t have these installed, then you will need to set them up before proceeding. Once you have these installed, you need to take the following steps:

  1. Open your Iron Speed application up in Visual Studio. You can do this by going to File -> Open -> Web Site which will bring up the “Open Website” dialog


  2. In the “Open Website” dialog, select your Local IIS and choose your website that Iron Speed Designer would have already created for you. Your Iron Speed project will not be opened in Visual Studio


  3. In the Solution Explorer, right click on the “Bin” folder and add the following references:


    1. In the .Net tab select “System.Web.Extensions”


    2. Then in the “Browse” tab navigate to the directory where you installed the AjaxControlToolKit. Then go to the “SampleWebSite\Bin” directory and select the AjaxControlToolKit.dll and add it as a reference also.


Rebuild your solution from within Visual Studio and you are now ready to start using the AjaxControlToolKit with your Iron Speed application.

Setting Up The ModalPopupExtender

Now that your application is setup, you need to setup your page for use with the ModalPopupExtender. For this demo, I’ll be setting up my “ShowTaskTablePage” with the ModalPopupExtender functionality.

  1. First you need to register the AjaxControlToolkit assembly on the page using the Register Page Directive. To do this open up the ShowTaskTablePage.html file in Visual Studio and insert the following code at the very top of the page:

    <%@ Register Assembly=”AjaxControlToolkit” Namespace=”AjaxControlToolkit” TagPrefix=”cc1″ %>
  2. Next you need to add your ModalPopupExtender underneath your generated table control on the page. You can either drag one onto the page from the toolbox or add one using the following code:

    <cc1:ModalPopupExtender ID=”ModalPopup” runat=”server”
    TargetControlID=”hiddenButton”
    BackgroundCssClass=”modalBackground”
    PopupControlID=”panel1″
    DropShadow=”true”
    OkControlID=”btnSavePopup”
    OnOkScript=”onOk()”
    CancelControlID=”btnCancelPopup”
    BehaviorID=”ModalPopup”>
    </cc1:ModalPopupExtender>


    At this stage, the ModalPopup has a number of properties that have values but need controls to be setup for them otherwise the modal popup won’t work.
  3. The first property we’ll set up on the ModalPopup is the PopupControlID. This property defines the control that will be displayed inside the ModalPopupExtender once we show it on the page. I’ve assigned a value to it called “panel1″ which is a panel that will house an “Add Record Control” that is generated by Iron Speed Designer.

    I’ll add the panel below the ModalPopupExtender using the following code:

    <asp:Panel ID=”panel1″ CssClass=”modalPopup” runat=”server”>
    </panel>

  4. Now I need to open up Iron Speed Designer and insert the “Add Record Control” onto the Show Table page. I simply added a new “Add Record” control to my page and configured it to use my Task table that I defined in the database.





    The final customization I made was to remove the Save and Cancel buttons from the control



    And now my control has been added to the page in the Iron Speed Designer under my Table Control


  5. Now I want to move the Add Record control to be inside the panel that I created earlier so that when the modal popup is activated it will show up inside the panel. To do this I switch to HTML view in Iron Speed, cut all the generated control text and move paste it into the page so it is nested within the panel control tags I created earlier. Your code should look something like this:

    <asp:Panel ID=”panel1″ CssClass=”modalPopup” runat=”server”>
    <GEN:Insert TYPE=”Panel” />
    <!– the rest of your panel code goes here –>
    </GEN:RECORD>
    </asp:Panel>
  6. Now when we created the control we chose to create it without buttons. You now need to add those in manually via visual studio. You will need to add two buttons to your panel, one for the “OkControlID” property and one for the “CancelControlID” property on the ModalPopupExtender. You need to make sure that you add your buttons inside the panel that we created earlier. I added mine below the Add Record control like so:

    </GEN:RECORD>
    <asp:Button runat=”server” ID=”btnCancelPopup” text=”Cancel” CausesValidation=”false”/>
    <asp:Button runat=”server” ID=”btnSavePopup” text=”Save” CausesValidation=”false”/>
    </asp:Panel>


    These controls need to go inside the panel because they will be visible when the ModalPopup is shown and will be used to control the actions of the popup.
  7. One annoying thing about the ModalPopupExtender is that it requires an ASP.NET control to be assigned to the TargetControlID. So what I’m going to do is assign a hidden button to the TargetControlID. This button will never get used because I’m going to manually show the ModalPopup using a javascript function assigned to the “New” button on the table control. So under the panel insert the following code to add a hidden button and then hide it inside a div so it still gets rendered to the page, you just never have to see it:

    <div style=”display:none; visibility:hidden;”>
    <asp:Button runat=”server” ID=”hiddenButton” CausesValidation=false />
    </div>
  8. The ModalPopup has the ability to run some JavaScript when the Ok event is fired from within the ModalPopup. This Ok script should be defined on the page and should correspond the value set for the “OnOkScript” property. I’ve simply created a script that returns true, but you can put any valid javascript you like in there. I’ve added my script just below the body tag in the html page.

    <script type=”text/javascript”>
    function onOk()
    {
    return true;
    }
    </script>
  9. The last little thing you might want to do is to add some styles to your Styles.css stylesheet in the styles folder. I added the following styles to mine:

    .modalBackground {
        background-color:Gray;
        filter:alpha(opacity=70);
        opacity:0.7;
    }

    .modalPopup {
        background-color:#ffffdd;
        border-width:1px;
        border-style:solid;
        border-color:Silver;
        padding:3px;
        width:500px;
    }


    This is the final stage in the setup and we are now ready to use the ModalPopupExtender.

Using the ModalPopupExtender

Using the ModalPopupExtender is pretty easy once you know how. We want to use this particular ModalPopupExtender to show when the “New” button is clicked on the table control. To make this happen we need to do the following steps.

  1. We need to write a little javascript function that will show the ModalPopupExtender. You can see this script below:

    function ShowModal()
    {
    $find(“ModalPopup”).show();
    }


    As you can see this script is fairly self explanatory, it finds the instance of the modal popup extender we want to show and calls the “show()” method.
  2. Once we have created our Javascript function we need to setup our table button to call this function when it is clicked. This is easily done in the Iron Speed Designer by right clicking on the button and selecting “Properties”



    Then in the Properties dialog select the Attributes tab and add a new Attribute Called Button-OnClientClick and enter the value to be “ShowModal();return false;”



    The reason we add the “return false;” is that we no longer want the page to post back and do whatever function it previously did. Setting return false; stops the button from performing a postback action to the server.
  3. Once you have done that, you are ready to view the ModalPopup in action. Build your application and click the New button to test it out.


This is pretty cool, but we want to be able to save the data we capture in the control back to the database. Lets look at some code for adding the data to the database.

Adding Data To the Database from the ModalPopupExtender

Ok we’re on the home stretch now and thanks to the power of the AjaxControlToolkit and the Iron Speed generated code, this final step can be achieved in just a few lines.

  1. First we need to add a bit of extra javascript to our onOk() function. As you saw earlier, we were just returning true, however now we want to simulate a postback from the webpage so we can save the data in the Add Record control in the ModalPopupExtender. To do this, we have to find the btnSavePostBack button and force a postback in Javascript because the modal popup extender blocks it by default. Here’s the code to make it happen:

    function onOk()
    {
    var btn = $get(‘btnSavePopup’);
    if(btn)
        {
         __doPostBack(‘btnSavePopup’,”);
        }
    return true;
    }

  2. Now that we have setup the code to postback to the server, we need to create an event handler in the codebehind that will save the data in the Add Record control and refresh the Table Control.

    Protected Sub btnSavePopup_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSavePopup.Click
    ‘Save Record To the Database
    Try
    Utils.DbUtils.StartTransaction()
    Me.TaskRecordControl.SaveData()
    Utils.DbUtils.CommitTransaction()
    Catch ex As Exception
    Utils.DbUtils.RollBackTransaction()
    Finally
    Utils.DbUtils.EndTransaction()
    End Try

    ‘Reload data in the table control and rebind it
    Me.TaskTableControl.LoadData()
    Me.TaskTableControl.DataBind()
    End Sub

    As you can see, this is just standard vb.net code for saving and rebinding the controls.
  3. Now this final step is where the magic happens. Ironspeed renders it’s table controls in updatepanels so you get “SmoothPanelUJpdates”. What we’re going to do here is add a trigger to the TablControlUpdatePanel that is wrapped around the TableControl which will force the table to update when the save button is clicked on the ModalPopupExtender. All you need to do is add the following code into the LoadData() method at the top of the codebehind:

    Public Sub LoadData()
    ‘ LoadData reads database data and assigns it to UI controls.
    ‘ Customize by adding code before or after the call to LoadData_Base()
    ‘ or replace the call to LoadData_Base().
    Dim trigger As New AsyncPostBackTrigger()
    trigger.ControlID = “btnSavePopup”
    Me.TaskTableControlUpdatePanel.Triggers.Add(trigger)
    LoadData_Base()
    End Sub

And that’s it, we’re done! Here’s some screen shots of the modal popup extender in action


No Tasks are in the List


I added some data and now we’re ready to save it


Click the save button and the table is updated without posting back to the server!


Aug 01 2007

Using Predicate Generic Delegates in VB.Net with .NetTiers

Category: .NetTiers, Programminglomaxx @ 11:23 pm

This post is absolutely essential if you use the Find method on generics lists in VB.Net with .NetTiers. Here’s some background. I was recently doing some work on an application that required me to loop through a TList that contained nearly 37000 objects and see if they existed in another TList that also contained around 37000 objects. So to achieve this I whipped up some code that looked a little like this:

For Each item As BaseAddress In lstProdContacts

Dim tmpContact As BaseAddress = lstTempContacts.Find(BaseAddressColumn.IdBaseAddress, item.IdBaseAddress)

'Use tmpContact here

Next

It worked, but the thing I found was that it was horribly slow. To execute on my list of 37000 contact it took well over 8 minutes which was simply unacceptable.

This post from the .NetTiers team pretty much confirmed what I had suspected and that this Find method was in fact using reflection. From my previous experience as a DNN programmer, I knew that reflection was expensive and should be used sparingly.

The post however, offered me an alternative solution: Anonymous Methods. However, this also presented another problem, VB.Net does not support anonymous methods. I was able to hack up some code that would use a wrapper class but it was all starting to get a little messy until I came across a brilliant post by Paul Stovell on Almost Anonymous methods in VB.net.

It wasn’t exactly what I wanted because I still had to define a function that would match the contacts, but it was a still a far cleaner solution. I put Pauls class in my Utility namespace and now when I want to use an (almost) anonymous method I do something like this:

For Each prodContact As BaseRfaAddress In lstProdContact

Dim tempContact As BaseRfaAddress = lstProdContact.Find(New PredicateWrapper(Of BaseRfaAddresse, BaseRfaAddresse)(prodContact, AddressOf ContactMatch))

'Use tmpContact here

Next

Then in the same class I define a function that will determine if a contact is a match or not and we’re done.

Public Shared Function ContactMatch(ByVal item As BaseRfaAddress, ByVal argument As BaseRfaAddress) As Boolean

Return item.IdBaseRfaAddress.Equals(argument.IdBaseRfaAddress)

End Function

It isn’t by any means as clean as anonymous methods in c# but now when I run the loop it runs in well under a minute which is an almost unbelievable performance gain and well worth the effort of implementation.