Showing posts with label Web Application. Show all posts
Showing posts with label Web Application. Show all posts

Friday, May 10, 2013

The benefits and horrors of third party controls

.. or how I learned to love the bomb

Don't reinvent the wheel
Don't reinvent the wheel (Photo credit: Wiertz Sébastien)
When developing web applications that should handle all sorts of data and potentially lots of it you might end up in building all kinds of controls for displaying and editing that data. Before you know it you are creating clever pieces of html and even cleverer pieces of backend code to produce that html and an added thick layer of Javascript sauce to make all this work together.
And that brings you into inventing another even cleverer mouse trap or re-inventing the wheel. And that mouse trap or wheel has to be cross browser and multi-functional, databound et cetera et cetera et cetera.
Me, I don't like re-inventing wheels, that has been done so many times already.
So, clear the stage for third party controls
Telerik
Telerik (Photo credit: martin.linkov)
One these re-inventors of wheels is Telerik. They have various suites of controls that make the life of developers easier. They have menu controls and date(time) edit boxes with calenders and grid controls that you can easily use in your applications. Set some options and bind them to your data and there you go.
I must admit that there is a bit of a learning curve, but with the help of some good examples on the demo site and the ever helpful support desk of Telerik you get everything up and running in no time.

As easy as .. whatever is easy.

But it is not all easy
When you start out all things go smoothly and then you find that on your page with a couple of nested grids you end up with many, many save buttons. As each (sub)grid has one. And thus starts the quest to use only one button to rule them all.

So here is our SaveAll Javascript function.

function SaveAll(button) {
    showLoader();

    $.ajaxSetup({
        async: false,
        cache: false
    });

    $('.t-grid').each(function (index) {
        var grid = $(this).data('tGrid');
        grid.submitChanges();
    });

    $('form').not('.t-edit-form').each(function (index) {
        $.ajax({
            url: $(this).attr('action'),
            data: $(this).serializeArray(),
            type: $(this).attr('method')
        });
    });

    hideLoader();

    $.ajaxSetup({
        async: true,
        cache: true
    });

    return false;
}
 What happens?

  • We start by showing a loader div (with spinning gif )on the page and so making it impossible for the user to do something while everything gets saved.
  • Then we make sure that all consequent ajax calls are asynchronous as we would otherwise run ito trouble.
  • Next we loop through all the grids submit all changes for each grid.
  • Then we loop through all the forms (excluding the forms with class "t-edit-form", these are are for inline editing in the grids) and we submit the forms through ajax.
  • Finally, we hide the loader div again.
There you are. That was not that difficult.
I have omitted checking for validation errors and what to do when everything is saved. Maybe we need to move to another page?
Well, it almost works, can I go home now?
Almost working is never enough for testers and clients. But is probably even more annoying for me as a developer.
We discovered a weird behavior in our grids. Because we wanted to unclutter our pages we also removed the delete buttons in the grids for removing records and added a column at the beginning of each row with a checkbox so the user can select multiple rows. Then using a delete button in the toolbar you can delete the rows in one go.
Great!
And then we discovered that the value of the first data column was not saved using our button. Other columns worked perfectly. The data was simply not in the request to the server.

After a lot of reaearch, Googling, trial and error
It was clear that the solution was just around the corner. The addition of the checkboxes was the cause. That was easily established, but a solution was more difficult.
Browsing through the Telerik Javascript code and the DOM I tried to add this to part where we are saving the grids.
    $('.t-grid').each(function (index) {
        var grid = $(this).data('tGrid');
        // save any editing rows first
        $(this).find(".t-grid-edit-row").each(function () {
            grid.updateRow(this);
        });
        grid.submitChanges();
    });
That would simply take the rows that are in editing mode and update the data. But no, this tried to update it directly on the server and that would involve additional writing specific server side code to handle those requests.
Close and still no cigar.
The problem was that the edited column was somehow not persisted in the client side data. So that was what  needed to be made sure. Persist all data in client side memory before submitting the grid changes.
But how?
More Googling
Trying evermore results from Google brought me to Paul Reynold's blog. In his post "enhanced batch editing using telerik extensions for asp .net mvc grid control" he explains a lot. Not all of it was relevant for my solutions, but I found a bit of code that helped to fix my problem. Thank you, Paul.

        $('.t-grid').each(function (index) {
        var grid = $(this).data('tGrid');
        // save any editing cells first
        $(grid.element).find(".t-grid-edit-cell").each(function () {
            grid.saveCell(this);
        });
        grid.submitChanges();
    });

I tried to update an entire row (which resulted in a server call) and the solution is to save each cell and these get persisted client side. Just what I wanted.

Lessons learned
I learned a couple of things in this quest:
  1. Third party controls are great for making life easier, because all normal functionality is there and tested.
  2. Third party controls make things really difficult at times when you want to do something slightly out of the box.
  3. Solutions can be found by hunting through multiple search results and reading all the way through these.
  4. Never give up.

Enhanced by Zemanta

Tuesday, September 23, 2008

Converting a WebSite project to a Web Application project

.. an interesting journey

In the last few weeks we have been preparing a conversion from a WebSite project to a Web Application project in Visual Studio 2005 solution. To complicate things a bit there is also SharePoint in the equation.

The reason to do the conversion was that we could not automate the build process in TFS and subsequently could not automate the deployment. Also the building of the solution itself within Visual Studio was handwork and took about forever.

What did we do?

Well, quite a lot was done to do the conversion. Along the process we were wishing louder and louder that someone had used his brain before picking the WebSite project. We had about 180 User Controls and about the same number of WebParts, that used these user controls. I know, what you want to say, probably not the best architectual design decision. But then again, when you do not take the time to think about the architectual design no one can put the blame on you for making the wrong architectual design . Duh.

We needed to do a two fold conversion: once for the User Controls and once for the WebParts.

TOKYO - AUGUST 06:  Surveillance humanoid robo...Image by Getty Images via Daylife
Converting the User Controls

We created a new Web Application project, deleted the Default.aspx and the Web.Config files and then copied all user controls from the WebSite project. Then we did a Convert to Web Application action through the context menu in the Source Explorer. This adds a.o. the designer files.

Using a specially written tool we processed all ascx and ascx.cs files to add namespaces, change and delete some of the attributes on the <%@ Control %> node. And we added a <%@ Assembly %> node.

Converting the WebParts

In the WebParts the UserControls were instatiated in the CreateChildPanel() method by calling the constructor. That needed to be replaced by a Page.LoadControl() command. Another tool was created to do that conversion.

Bumps in the road

We first figured the process out by creating a small and simple Proof Of Concept. That worked like a breeze. Then we started on a copy of the real code. Yep, that's when the manure hit the propellor. We came across multiple problems, mostly because of inconsistencies in the coding. Sometimes there were comments when did not expect them or a code file was not placed in the correct folder. So, some of our assumptions failed and we had some manual clean up after our conversion tools. But that was limited to roughly 20 files. Not too bad.

But we also saw that our Proof Of Concept was many times less complicated than our real world code. That kept us busy with debugging for quite a few days. That and the fact that we were not experienced SharePoint deployers did nt help speed things up.

Ready to roll

Last friday we were ready to roll. We had figured everything out and had fixes for all the small problems that we encountered. So, the monday was set as the big conversion day. We mailed our offshore team in India to stop any work on the code around noon and made a branch in TFS.

The Big Bang conversion

With the script in hand we took the steps one at the time and started the conversion at half past one. Ticking off each step we were ready to try and compile about an hour later. More manure hitting the fan. Some caused by missing references and some by the new code that was created by our friends in India. They did coding while we were testing out the conversion so we were now working with a new code base. So afcing some new interesting bumps.

We only had to do some things a second time, having forgotten to update one of our conversion tools. Gradually we saw the number of build errors go down from 300 and then up a bit again. And finally at half past seven we had a fully building situation we then checked in in TFS.

Today

Today, we hear some enthousiastic noise from fellow developers who find that the solution compiles a lot easier, without any manual building of separate projects and above all a lot faster than before.

Also we are now starting testing the deployment and ironing out any last bugs that are in there.

Lessons learned

The most important lessons learned is that especially in bigger application development projects it is absolutely necessary to think before you do, design before you start building as that will save you loads of time and trouble later on.

Further we have learned a lot about conversion and file manipulation through RegEx and changing files loaded into MemoryStreams which was an interesting excercise as well.

Reblog this post [with Zemanta]