Tuesday, February 18, 2014

Email discussions

.. they just don’t work

We have all been there. Probably multiple times as well. The endless sinkhole of discussions running on email. Someone send you an email or replies to an email you send or you are just one of the innocent bystanders that are in the CC-list. That email then triggers yet another reply from someone, for some trivial reason maybe. But then the avalanche starts. Avalanches usually start with just one small ball of snow. The effects of an avalanche can be disastrous and so are the effects of an email avalanche
Do not play with dynamite in the mountains
It is really easy to react to some incorrect or plain stupid email. Or something that just annoys the heck out of you. A manager happily announcing to a customer that we will be shipping next week and joyfully CC-ed you along in the mail.
Enough to make your head explode and maybe even go ALL CAPS on him.
It’s so easy to fall into the trap. It is so easy to try and start a discussion via email by simply pressing reply and start typing. Often without really letting your brains kick in. With a healthy strong cup loaded with cafeine you can really get the words and long sentences flowing. After banging prose for several minutes you sit back and admire your work and know for 100% sure that this will solve all misunderstandings and will re-eductaed all those on the list of addressees.
But in reality you hold a match very close to the fuse of a stick of dynamite.
When you hit send you light the fuse.
Boom!
You return to work and after some time you check your inbox and disaster has struck. An avalanche of replies to your solve-it-all reply. People have written long epistels back explaining things again and how everything was agreed upon and what was not agreed upon and that they weren’t there when it was agreed and that the situation has changed and soon some will GO ALL CAPS ON EVERYONE INCLUDING YOU. YES YOU!
You see that more and more people have gotten involved and that more people are receiving the mail and oh yes just like an avalanche it has gone rapidly downhill.
Maybe someone is accusing you or anyone else already of being a Nazi.
Stop right there
Yes, it is already too late. So stop replying. It is simply impossible to get switch on sanity again in this situation. Stop it.
The only solution right now is get face to face with the people really involved in the matter. Which you should have done right from the beginning.
Single out the most relevant people in the matter and send a meeting request. Get face to face or if itis just one or two people get on the phone or Skype or Hangouts or whatever you prefer. Quit the email avalanche which is making things worse with each reply.
Better stil..
Better is to prevent the entire escalation. Whenever you find yourself writing a big email reply and you feel your heart beating stronger than normal and you drink your coffee faster than normal, please do not hit that send button.
Cut and paste the text you have written in a document and turn the email in a simple meeting request. You can use the document as your notes for the meeting.
The words “Let’s meet and discuss” are so much more powerful than any piece of well written prose no matter how long.

Thursday, January 30, 2014

Trying to get back into blogging

.. and it's a struggle

I have been planning and  planning to write more on this blog. I have been trying to at least write a single piece again on this blog. It has been way, way too long since the last post. It's been some eight months now. Bummer, that's bad.
Looking back over the years I can see that my blog has been drying out. Nothing comes out of the well anymore. That is not good.
Let's take action
Blogging has been on my list, always. It still is. Simple as that. But so have many other activities. Including work. And hobbies. It has been difficult to find the right balance to do everything I want to do. I have scraped some subjects in Google Docs but have never gotten around to work these out into proper blog posts. There is more needed for that than just a few more lines of text.
But anyway I need to take some action. I need to look for and find the time to pick things up again.
And I have found a tool: Lift. It’s a tool for achieving goals and literally lifting you up again. There is also an app in the Play Store and on iTunes.
Daily motivation
Pick a plan in Lift and you get a plan divided up into simple steps that you can take daily and slowly and surely achieve your goal. Having done a task simple check it and optionally add a comment. Other Lift users can give you props for the achievement and can also start a discussion to help you or others achieve their goals.
This is truly a form of daily motivation.
One of my goals is writing
I picked one of the goals to get me back into writing more regularly and so far it has helped me a lot. This blogpost is one of the products to prove it.
There are other plans that I have chosen and that help me to get more grip on my goals in life. I find it a great tool to help me help myself with some help from unknown friends.

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

Thursday, April 04, 2013

Multiple submit event handlers on Ajax forms in a wizard style application

.. this was driving me crazy!

I was working on an application (ASP.NET, MVC3) in which I had to implement a wizard like piece of functioality. You know of the 'Next-Next-Previous-Next-Finish'-type.
To make things nice for the user I used AJAX. To make things simpler for me I have one control that is loaded and depending on the page that the user is currently on I load different controls into the form. I return a PartialView and that replaces part
That is all not too complicated and works like a charm.
Uhm, no it doesn't
The first page shows up. I hit the submit button and the page went by smoothly and I could see the ControllerAction being hit. Great! I just increased the page counter and onwards to the next page. The next page arrives in the browser and I hit the submit button again.
Uh oh! Things go wrong now. My ControllerAction is hit twice! Worse even on the next page, it gets hit three times! Oh my, oh my.
Inspection of the problem
Looking at the html closer I quickly discovered that the form had multiple event handlers tied to the 'submit' event. This was the cause of the forms being submitted multiple times.
How come these multiple event handlers then?
Apparently the jQuery Ajax (jquery.unobtrusive-ajax.min.js) has some trouble with the Ajax replacing a part of the DOM and then reattaches some of the existing 'submit' Event handlers. The extra event handler on each page is thus explained.
Root cause is that the AJAX call reloads part of the DOM including the FORM-element and not the content of the FORM and thus somehow the old submit eventhandlers are not cleared. Hence, multiple event handlers.
Okay, so let me Google that for you
Or Bing it. Or Yahoo it.
Many people have encountered similar problems. But none quite the same as mine or at least the provided solutions did not solve my problem. And so I experimented with many solutions and all of them failed.
Thought about somehow preventing all the event handlers but the first to fire. Or just to delete all event handlers except the first. Couldn't find a good way of doing that.

Back to the drawing board
Completely rebuilding the Views and PartialViews to refresh the DOM inside the FORM element was not an option. So that was ruled out.
In the end we decided to go a slightly other way. We decided to step away from a normal submit button as that triggers (all) the submit event handler(s) of the FORM and makes us lose control of the mess we got in. We created a simple button that calls a JavaScript function that does the submit of the FORM through jQuery AJAX. This way we never ever call the submit event handler of the form.
Problem solved.
Please find below the simple JavaScript function that does all the clever stuff.
function onSingleSubmitButtonClicked(button)
{
  var frm = $('form');
  var data =  frm.serialize();
  var url = frm.attr('action');
  var method = frm.attr('data-ajax-method');
  var target = frm.attr('data-ajax-update');
  $.ajax({
    type: method,
    url: url,
    data: data,
    beforeSend: function() {showLoader();},
    complete: function(response) {$(target).html(response.responseText);hideLoader();}
  });
}
We attach this function to the click event of input[type=button] and that is all. Below a step by step run through.
  1. The function finds the one form on our page. When you have more forms on a page you may have to pass an id or when the button is inside the form find the parent of the button of type FORM.
  2. Next we serialize all the input fields from the form.
  3. We then grab the action attribute from the form and use that as the url to post the data to.
  4. We read the post or get method from the appropriate method.
  5. The update target where we will put the response from the Ajax call into the DOM.
  6. Then we make the Ajax call. The serialized data is included and we also show a loader overlay before we send the request and hide it again after the call is complete.
Probably some optimization is possible, but that is a simple solution to the weird problem. Just take things in your own hands. You can't always trust the browser or jQuery do things the way you would expect them to do.

Monday, December 05, 2011

Creating a master-detail grid with Telerik ASP.NET MVC controls

.. with a twist

Right now I am part of a team that is building a big HR related application. Maybe it's better to call it an HR suite. When finished it can be used to do performance reviews, 360s, development plans and the like with this application. It will be big and the customer plans to conwuer the world wit it. Well, at least Europe.
Architecture
For this applications some choices were made with regards to the archictecture.
First decision: we use ASP.NET MVC3. Why? Well, main reason is that this is becoming some sort of standard way of developing web applications using .NET. Is it the best way? Is the easiest way? Is it the only way? No. No. No. It is one of the possible frameworks to use. And because we expect to get more people on board we pick a framework that more people use over own framework.
The second choice we use Entity Framework and with that the Code-First option. This was a first for us and it takes a bit getting used to not have to write any clever stored procedures.
Database access is separated from the web application and is handled through web services. Making it so much easier to later decide to share the load over more machines.
Finally, a decision that was already made by the client, we should Telerik Components were possible.
Getting back to the subject
Ok, let's get back to what this really about. Implementing a master-detail grid with a Telerik component.
So why a blog post on this? Telerik has an extensive demo site and has a demo on a master detail grid. Yes, they have, but we want to do it slightly different.
To be totally honest, we think that the standard way of ASP.NET MVC3 is in some repect a step back. Done the simple way it means that a lot of the logic is done in the aspx page. It comes close again to classic ASP. Mixing markup with C# code and ending up with not optimal code in both of these areas. We are great believers in Object Oriented approach and we seek to reuse as much code as possible and want to kae our controls as clever as it needs to be.
Beacuse the target market is Europe we have to cater for different languages and we have solved that problem in a base control and derive all controls from that.
In the aspx page, we only want to load a custom user control that we build up completely in code. No, we did not go down the Razor path.
So yes, we have private controls and we override the CreateChildControls() method. We do the binding in the OnPreRender() and finaly in the Render(writer) method we make sure the correct markup is being produced.
Brining in the Telerik controls
The above approach also means that we cannot use the Telerik components as private controls. It is not possible to instantiate the components. So in comes the Telerik.Web.Mvc.UI.Fluent namespace and a variety of Builders. With these builders it is relatively easy to build the component. When we have set all properties we want and bound the data we then use the method ToHtmlString() to get the markup produced by the component and assign that outcome to a LiteralControl. After that we let the rendering go on in the nromal way.
This way we can use our own OO-based control hierarchy and still use the powerful Telerik Components. We do not wish to completely build (and test) a sortable, pageable, editable grid control.
Now for the Master-Detail grid
In one of our Use Cases we needed a Master-Detail grid. No problem the Telerik Grid component supports that as shown in the demo.
The problems was how to get that done in our approach using the Builders. We did not find any real examples of this.
Telerik support team
So then we got into the normal horror of sending a question to the support desk. Normally it takes some days to get a reply and then you need a couple of messages to get them to understand your question and then explain why you want to have it done the way you are doing it. Before finnaly, you get into the struggle of getting an answer that really works.
But no wait!
The Telerik support is different!
They reply within 24 hours as advertised. I even had an answer with ten minutes on one of my questions.
And they quickly understood what I was trying to and gave me enough info to solve my problem with a workday. And being probably in different time zones I think that is a wondeful achievement! Many thanks for that!
As a big thank you I wil explain what the final solution was.
The problem
We want show a grid with all the departments of a company and we want to click open (expand) a department to show a list of it's employees.
Nothing too special.
The solution
Our data model is pretty simple:
Department
Properties
  • Guid DepartmentId
  • string Name
  • List Employees
Employee
Properties
  • Guid EmployeeId
  • string FirstName
  • string FirstName
Our control has a LiteralControl that will be the placeholder for the markup produced by the GridBuilders. Also there is a private field that holds a list of Departments with the corresponding Employees.
Let's start using the GriDBuilder to first create the Master part.
GridBuilder gridBuilder = HtmlHelperExtension.Telerik(viewPage.Html).Grid();
            gridBuilder.Name("MasterDetailGrid")
               .DataBinding(dataBinding => dataBinding
                   .Server())
               .BindTo(departments)
               .Columns(columns =>
               {
                   columns.Bound(d => d.Name).Title("Department");
               });
This is the normal way to use the GridBuilder to create a Telerik Grid.
The Detail part of the Grid is itself also a Grid, so we can use teh same approach.
GridBuilder employeeGridBuilder = HtmlHelperExtension.Telerik(viewPage.Html).Grid()
   .DataBinding(dataBinding => dataBinding
   .Server())
   .Name("Detail")
   .Columns(columns =>
   {
      columns.Bound(d => d.FirstName).Title("FirstName");
      columns.Bound(d => d.LastName).Title("LastName");
});
Note that I have not bound this Deatil Grid to anything yet. That is something we need to do as part of the master Grid. To do so we need the DetailView method of the Grid.
gridBuilder.DetailView(dep => dep.Template(d =>
   {
      employeeGridBuilder.BindTo(d.Employees);
   }));
This makes the Employee bound to the Employees of the Department that is in the row of the Master part of the Grid. Now, spit out the markup and put it in the LiteralControl.
literalControl.Text = gridBuilder.ToHtmlString();
But nothing shows up for the Employees. We ca expand a Department row and there is some white space, but no Employees.
The final step
Something inside my head said that I had to use ToHtmlString() on the detail Grid as well. But I could not find the correct syntax. So back to the Supprt Team at Telerik and an answer came very quick. It was simple as the following:
gridBuilder.DetailView(dep => dep.Template(d =>
   {
      employeeGridBuilder.BindTo(d.Employees);
      return employeeGridBuilder.ToHtmlString();
   }));
This makes the detail Grid appear and now we can move forward again full speed!
Thansk again!
Not only does Telerik produce great components, they can be used in various ways. Even the not so standard way we want to use them. Telerik also has a super Support Team is both fast and correct in their answers.
If you ever run ito a problem with Telerik components they will surely be able to help you out in no time!
Enhanced by Zemanta

Wednesday, September 28, 2011

I was shocked

.. and then I laughed

Mosaic?

.. wasn't that the first browser?

I must admit that back in the old days when cows still walked barefoot in the meadows I was browsing the Internet using the Mosaic browser. That was a very, very log time ago.

But this blogpost has nothing to do wth that.

Blogger views

Blogger (which hosts this blog) added a dynamic view mode that allows the user to view a blog in a number of different ways. One them is "mosaic" that I think can provide in a snapshot what a blog is all about.

Blogger is just one example of how Google breathe new life into a product. They have done this by "rotating" it to a new team and it's great to see that they keep innovating on a product that's been around for so long.

Here's the link to see this blog in the mosaic view: http://roho2003.blogspot.com/view/mosaic and you can change it to one of the other dynamic views with the menu in the upper left.

Enjoy!

Friday, July 01, 2011

A multimedia super machine

.. what would that be today?

Today the multimedia business is rapidly (r)evolving with ever more possibilities and more machines are coming together. Telephone, Internet and TV are converging with more and more functionalities coming in as well.
I find it difficult to keep up to date, but still I try. Every month, it seems, some new gadget comes onto the market that has some completely new amazing function or a better way to do something an other device already did. It's hard to keep up with it.
My multimedia center is not yet complete
Although my multimedia machinery is relatively complete I still miss some functionality. I can not playback all the movies I hold on my NAS (DLNA enabled) and I can not record TV shows. Or time shifting. I can do some browsing on my TV and on my Wii but neither is great.
So there are somethings that I would want to add to my setup. But I only want to add a single machine that holds all possible options I can think of. At least that I can think off today.
If only I could think of all the options available today.
And that's where you come in
Since it is impossible for me to compile the list of maybe all the options that are out there at this moment I have decided to crowdsource this task. I have shared a Google Docs document that you can freely edit.
Please bear in mind that I don't want the machine to make coffee, do the laundry and walk the dog. So please only realistic requirements for the machine.
So if you want to help me find the requirements for my next Multimedia Super Machine just click the link and add to the document.
Many thanks in advance!

The results so far
Have a lookie!

Scroll about :-) or just click the link and have better view and maybe even add or correct.
Enhanced by Zemanta

Thursday, June 16, 2011

Using simple jQuery to detect changes

.. a quick solution

Updated
Today I had a small task assigned to me to prevent a user from navigating away from a web form when there are unsaved changes. As it was a rather extensive form (and old code) I had the feeling that it could be quite an extensive task.
Yes, I know this is more of a beginner's level blogpost, but maybe someone can use it. Otherwise burn me down to the ground in the comments.
General idea
A simple solution came to mind:
  1. do this on the client
  2. in comes JavaScript and yep, here comes jQuery!
  3. have a page wide boolean isDirty that starts as 'false'
  4. when an input control is changed, make isDirty 'true'
  5. when user tries to leave the page, check the value of isDirty
  6. when isDirty is 'true' show confirmation dialog
  7. if the user cancels stay on the page
  8. if the user ignores then proceed onwards
All rather simple.
Let's implement this!
Steps 1 and 2 are easy to take. We will just include the jQuery library in the page and start a block of JavaScript.
Also simple is step 3.

var isDirty = false;

Step 6,7 and 8 can be wrapped in a simple function:
function IsPageDirty() {
   if (isDirty) {
      var ignoreChanges = confirm("Unsaved changes. Proceed anyway?");
         return (ignoreChanges);
   }
   return true;
}

That was easy, as some would say.
Now the final leaps
Then I decided that it would be simple a matter of using a selector in jQuery and add a function to the change function that sets the isDirty boolean to 'true'.
I opted for a class 'trackChanges'.
This is the little snippet that I produced.
$(".trackchange").change(function() {
   isDirty = true;
});

Similarly I chose a class of 'moveaway' for those links that can lead the user away from the current page. These links should get a onclick attribute returning the the result from the IsPageDirty() function described above.
$(".moveaway").attr("onclick", "return IsPageDirty();");
And then there was a lot of work ...
Since I then had to go through the entire form. It was an aspx page and there User Controls (ascx) being loaded and I had to go through thse as well. Not very pleasant.
I got myself another cup of coffee and had a good thought. Then I decided to just select all input controls and not just certain marked with a class.
Changed the code to the following.
$("input, select").change(function() {
   isDirty = true;
});
Same was true for all the links. I opted for selecting all anchors.

$("a").attr("onclick", "return IsPageDirty();");

Then I had a huge problem, because the saving was also done using a link. Before the saving would start the user gets a warning that there are unsaved changes. A bit confusing to say the least.
I didn't want to go back to putting a class on all the other links just to get around this. I wanted filter out some of the anchors by putting a class on these.
Luckily, jQuery has a function .not() that takes a selector and filters out these from the selection it is applied to. So I put a class 'always' on the anchors that should not have the IsPageDirty() check and changed the line to:

$("a").not(".always").attr("onclick", "return IsPageDirty();");
And that was it! A very simple piece of JavaScript code and hardly any changes to the page itself. I only had to add a class to some of the links.
Bringing it all together
Even if it is a very simple scenario and the code is probably not as compact as it can be, I think it shows once again how versatile JavaScript is in combination with library like jQuery.
So to get all together

<script type="text/javascript">
   var isDirty = false;

   $(document).ready(function() {
      isDirty = false;
      $("input, select").change(function() {
         isDirty = true;
      });
      $("a").not(".always").attr("onclick", "return IsPageDirty();");
      // a with class "always" is not checked
   });

   function IsPageDirty() {
      if (isDirty) {
         var ignoreChanges = confirm("Unsaved changes. Proceed anyway?");
            return (ignoreChanges);
      }
      return true;
   }
</script>

Not earth shocking
I know, I know, but still I think it could be of some help for others somewhere on the web. And maybe to help me remember this for future reference.

Small update
The above solution worked on almost all of the pages, but one of the pages had some ASP.NET AJAX stuff on it, where dropdownlist were filled after the initial pageload. This caused some nasty problems, because these made the
change()
function go off and set the
isDirty
variable to true.
Some scratching of the head and then some Googling made find the
live()
function to be my saviour in this.

<script type="text/javascript">
   var isDirty = false;

   $(document).ready(function() {
      isDirty = false;
      $("input, select").not(".ignore").live("change", (function() {
         // control with class "ignore" does not fire the isDirty flag
         isDirty = true;
      });
      $("a").not(".always").attr("onclick", "return IsPageDirty();");
      // a with class "always" is not checked
   });

   function IsPageDirty() {
      if (isDirty) {
         var ignoreChanges = confirm("Unsaved changes. Proceed anyway?");
            return (ignoreChanges);
      }
      return true;
   }
</script>

A reader with a good eye also notices the
.not(".ignore")
function I added to exclude some controls from firing the isDirty flag. I used this class on some input controls used for search.

That's it for now!
Enhanced by Zemanta

Wednesday, June 08, 2011

Connecting Visual Studio 2008 to TFS 2010

.. a note to self

And amidst all new versions of Visual Studio and Team Foundation Server I find myself at a client where there is a mixed codebase. Some older stuff created in VS2008 and even VS2005 and now working in VS2010. Luckily, they have their code on TFS 2010. For each version of Visual Studio code there is a collection aptly named VS2005 et cetera.
But then I struck the small challenge of actually getting to older code. I could connect to the collections using VS2010 and get latest from there and then I could open it using the correct version, but I completely lost the ability do any real source control.
I could not simply connect the older Visual Studio versions to TFS2010.

Now what?

Luckily this is something the people at Microsoft have anticipated. There are Forward Compatiblity Updates for older versions of Visual Studio:

Almost there

When connecting to TFS2010 from older Visual Studio versions wen need to give a little more data than just the server name. The complete path to the collection is needed. You will get a TF31002 error when you only provide the server name.
In the Add Team Foundation Server dialog you will need to enter the following format in the Team Foundation Server name textbox:

  •  http://{tfsserver}:{port}/{virtualdir}/{projectCollection}

In my situation I came to the following result.

And another trick learned
I hope this helps someone else as well. At least it is a note to self.
Enhanced by Zemanta

Thursday, April 28, 2011

Barefoot running

barefoot running(for this my feet are too sensitive)
Image via Wikipedia

.. it is something completely different

For some of you this will seem like a completely misplaced post. It is not about developing or the Internet or Google but about running.
In my sparse sparetime I like to do some running. I have done that since my days in University on and off with more or less intensisty. Still haven't run the obligatory marathon yet, but two Half Marathon should count as one, I guess.
Traditional running
I have always tried to run on a good pair of running shoes and replace these every 300++ Km to make sure I have sufficient damping. Not doing so always made my muscles hurt and led to small but painful injuries to my knees.
Ever since working for Nike I run on Nike shoes as these suit me very well. It's been a couple of years since I left that company but still the various Nike Air dampened shoes do their job wonderfully.

Time and shoes are changing
Lately new ideas about running shoes are getting more and more mainstream. The fully comfortable running shoe now has a version which more close to nature. The idea being that the foot loses its natural stability and muscle power since it is comfortably supported and strapped in inside a sturdy and soft and easy dampened shoe.
Natural running is closer to the way many of the African athletes train: on their bare feet.
Natural running supposedly makes your feet muscles stronger and also changes your way of running and ideally improving it.
When I was in the Nike Headquarters in Beaverton, Oregon in 2003 I was shown one of the prototypes of the Nike Free shoe. The Nike Free shoes have a very flexible outer sole and the top of the shoe gives less rigid support. You can role them up easily.
But still they provide quite a bit of damping.
The Vibram Fivefingers are a whole step further. They are completely minimalistic. No damping and the upper part of the shoes is as light as possible. To provide even more freedom through the use of five separate toe compartments.
The outer sole is, as can be expected from Vibram, a good wear and tear resistant rubber giving good grip but also minimal damping. With that the Vibram Fivefingers come much closer to true barefoot running than the Nike Free concept.
Being a bit of a geek
Yep, as the geek I am, I was interested in both the Nike Free concept and later on also the true "barefoot running" idea. I wanted to try them sometime. But it never really happened.
Until I saw a tweet come by on my Twitter timeline. It was one of those "retweet this and you have chance to win ...". This time you could win a pair of Vibram Fivefingers. Not really expecting to win anything I did retweet and went on with my work.
Want to win FiveFingers yourself?

Easy!  Go over to this page and hope for the best!

A few hours later I found myself exchanging my shoesize and address to receive a pair of Vibram Bakilas!

 First impressions
Now I have them for a couple of weeks and I have been running them on ever longer stretches. I must say that I am completely amazed by them.
It takes some getting used to and I am still trying to find a new perfect style of running. But I think that is something positive. On my normal luxury running shoes I never really think about the way I run, I just put one foot in front of the other. I do pay some attention to my arms and upper body, but that's it. Most of the running is done without thinking about it. In this respect barefoot running makes me thinking about the way I walk.
The other part that really amazes me that I do not feel anything special in my muscles. I had expected that without the shock absorbing sole I would feel my muscles and knees. Whenever the absorbing qualities of my normal shoes would drop these are the first things I notice.
But even with close to no shock absorbing there are repercussions. This amazes me still as I gradually build of the length and intensity of my runs.
I still run on my Nike shoes, but I try to do every other run on my Vibrams.

Conclusion
I must say that this barefoot running on the Vibram Bakilas have more than amazed me. I am truly enthousiastic. As I have no Nike Free shoes to compare them to (hint hint) I can't comment on that.
At the very least the Vibrams have made think about my running and my posture and also they have once again breathed new life into my running adventures.
I love my Bakilas!
Finally
Some other things you can do with Vibram Fivefingers ;-)





Enhanced by Zemanta

QR codes

.. every blog should have one

Since it seems to be part of a hype I can not be left behind.

Enhanced by Zemanta

Tuesday, January 18, 2011

The module was expected to contain an assembly manifest

.. Could not load file or assembly 'Microsoft.ReportViewer.Common..'

In the project I am currently involved in we had created some nice reports and had these render directly as PDF file to the browser. Worked great on my machine and on my colleague's machine. And then deploying it to our test environment that sits on a shared hosting server it failed.
Could not load file or assembly 'Microsoft.ReportViewer.Common, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The module was expected to contain an assembly manifest.
Clearly a security issue that will easily go away when you put the necessary assemblies in the GAC. But with shared hosting that is probably not an option. The hosting party will allow that nor facilitate.
Monday Monday ~~~~~~~~~~~Image by Trish Hamme ≧◡≦ via Flickr
Trying to figure out a solution
It took some Googling about with not much result but then I found this webpage that explains a simple solution to the problem. And hey presto! It works! Thanks, Desirée Harris from OrcsWeb. You just made our day!
Enhanced by Zemanta

Wednesday, December 22, 2010

Coding practices, part 1

.. hold on tight

Various have been the places I have worked at and even more so the people I have worked with. Sometimes it was a good experience where both parties benefited, but sometimes it was a struggle.
One of the downsides is that I have had to work with code produced to varying standards if there was something like a standard at all. In this little series of blog posts I will highlight some of the examples that I have encountered over the years. Most of these are related to C# but probably apply to more situations. If so, you have my condelances.
Make me search like forever
One of the great things of freedom in structuring classes, codes and files is that you can do things in all kinds of ways. That is exactly the downside as well. You can put things all over the place without any logical connection between them:
  • Put multiple public classes in one file.
  • Name the file different from the class that’s inside.
  • Don’t use the namespace according to the folder the file is in.
  • Name the project different from the name of the assembly.
  • Put in a folder with yet a different name.
  • Cherry on the cake: make it completely different in source control where possible.
I only hope that this covers all possible obscurity.
Taking for granted that we now know every possible option
Let's consider a simple enumeration giving us a choice of direction.
public enum Direction
{
    Left,
    Right
}
Now let's say you are at least clever enough to consider using switch-statement instead of a if-statement to implement this in your code. Still, you have multiple ways to make this work or not.
Suppose you need this in a method that returns something based on the direction.
Good
Be sure to have a default option.
switch (direction)
{
    case Direction.Left:
        return SomethingLeft();
    case Direction.Right:
        return SomethingRight();
    default:
        return null;
}
Better
Maybe returning a null-value is not desired or maybe even SomethingLeft() can return null then it's probably better to throw an exception.
switch (direction)
{
    case Direction.Left:
        return SomethingLeft()
    case Direction.Rightt:
        return SomethingRight();
    default:
        throw new ArgumentOutOfRangeException("direction");
}
Bad
Somepeople think that writing less code is better.
switch (direction)
{
    case Direction.Left:
        return SomethingLeft();
    default:
        return SomethingRight();
}
What now if someone thinks we shoud be able to go 3D?
public enum Direction
{
    Left,
    Right,
    Up,
    Down
}
A right-handed Cartesian coordinate system, il...Image via Wikipedia
Or maybe an old sailor becomes architect and decides to use this:
public enum Direction
{
    East,
    West,
    North,
    South
}
We could do something like global search and replace or a refactor action, but the bad code will probably not do what we want.
Seen all these
I have seen the above examples and have frowned at them. I have improved the code where possible and have given up on trying to educate some of the people who wrote the code.
More examples will follow.
Enhanced by Zemanta

Monday, November 22, 2010

A very weird bug

.. with an even weirder resolution

The other day I was working with a consultant from another firm to try connect our systems together. Previously we had exchanged WSDLs and even a stub service so we didn't expect to many problems implementing the real stuff.

The other client had brought his own laptop and that was quickly hooked up into the network. That was an easy start.

But ...

Things started to get really weird when I tried to connect my client app to his service. To make it a little more clear to you all: the service was a .NET 3.5 WCF Service and I was consuming it using a .NET 2.0 webservice client. The 2.0 bit was manadtory as our application is still limited to that version of the .NET Framework.

We were greeted with the following very weird error:

The message with Action 'http://tempuri.org/ITheOtherService/GetObjects' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

Googling it didn't give me a clue.

To add some more info: he was running his own domain and Active Directory on his machine. And I also had to use a NetworkCredential to get access to the service. I could see the MEX output in Internet Explorer (using the correct credentials) so connection was verified. We were connecting using the IP address of his machine.

Question marks all over

Completely baffled he gave me a test application that he had used to test the setup with a colleague in his office. We got a error message that prompted me to add the hostname and IP address to my hosts file. We had an error about linked XSD files that couldn't be found because the hostname could ot be resolved.

After that little hack we had no problem making call and getting results. Completly stunned we stared at our screens. OK, fine by me.

The big application where all the work was made still did not function. Still showing the same error message.

Another even simpler app was created, making a simple call to the service. And it worked. But still not in the big application we needed to hook up.

Details are the devil's hiding place

In another test run I then saw that I had configured the big application using the IP address. The hostname was not yet in the hosts file when I first configured the service address.

The test applications we used both of them used the host name in stead of the IP address and they worked.

After having changed the configuration to use the hostname evrything started working.

I still haven't found out why it did.

Well, who cares?

We then continued to do the testing and had to make onlysome small changes as we both had done a great job in building our apps to mutual specs. So, it was all in all a great success. But something keeps itching me.

Well, who cares why it worked with hostnam? Well I do care! I have no real idea what the reason is why it worked one way and not the other. SO, if any of you can point me to the reason of this, please leave it in a comment.

Also, maybe this story helps you to solve your weird error. If so, please leave a commoent.

Monday, November 15, 2010

A discussion about creation

.. too early in the morning

Every now and then I am invited to a job interview to sit at the employers side of the table.'That is kind of fun as well. I do enjoy sitting on the other side, because I have the feeling that I am the one who is to make the decision whether to take the position or not. Once they have invited me for the interview I am pretty close to getting hired. At least that is the mood I try to get myself into on most of these occasions.

As I am a developer I mostly attend the interviews for developers. I am usually the ally of the prospect in that sense. The manager that sits there as well is most of the time a non-developer. Someone who knows we need someone with .NET and C# skills, but has no real idea what that means. I am there to see if he or she has any real developer's skills.

Questions to ask

A colleague of mine has very goo question to ask the candidate. He tells the candidate that we would like the manager start programming or at least understand some more what we are doing. One of the things the manager still can not understand is, what is Object Orientation? Can the candidate explain that so the manager can understand the concept. I have heard some hilarious answers to that question. One of the apparent advantages of Object Orientation is that you can spread the objects across multiple servers. The same candidate explained some of the aspects of OO with a dog as an example, one the methods could be Bark() or Sit(). When asked how one would distribute such behavior across multiple servers he fell silent.

Another good and slightly more tricky question to ask is about difference between the terms class, type and object. I must admit that I had to think about that one to come up with a good example. I propose the following example of a Person class, with as properties: first name, last name and birth date. Let's pass those along in the constructor and you get to the following code:

Person person = new Person(firstname, lastname, birth date);

The first word "Person" is the type of the object "person" being created. The class is Person in which a.o. the used constructed is found.

All right, purists, kill me in the comments, but it gently.

A question to ask

I then started to let my mind go wandering where it will go.

I thought about namespaces. I happened to have been in some discussion with namespaces and doing it better than it was in common practice at this job I was at.

The class Person would be in something called

  • Human

Then I started expanding:

  • Nature.Human
  • Earth.Nature.Human
  • Creation.Nature.Human
  • God.Creation.Nature.Human

Hmm, sounds like intelligent design. Note that I haven't named God, that would turn off some other Persons from the namespace Hardcore.Christian.God.Creation.Nature.Human.

Or for those rather having the Evolution Theory, it could be something like:

  • Darwin.Evolution.Mammal.Primate.Human

But working along these ideas, ultimately, all namespaces would be positioned below God or Darwin. That would be strange idea. And what about the Flying Spaghetti Monster?

The God Class

Then I found myself wondering about the God class. "You should never create a God class." It must be one of the ten Developer's Commandments. Which namespace would that God class be in? I became stuck at this point. I at least understand now why I should never creat a God class, because there is no namespace to put it in.

On top of that does the God class derive from object? Or from a divine object? Or the other way around: does object derive from God?

Philosphical

So, there I was completely philosophical before 9 in the morning. Suffice to say, I didn't get much work done all day. Especially no Divine Work.

Please someone help! Define devine!

Friday, November 12, 2010

Scope creep can be nasty

.. but scope run seems worse

I've had it happen way too often on me: scope creep. Slowly, but surely small things get added and one moment you notice that way too much things are happening and need to be done on that small project.

I have been there and seen it and let it happen and still let it happen way too often. Almost every project scope creep comes creeping in.

But it can be worse

What is also possible in these 'agile' processes that are so hip these days that scope creep can go so fast that it not just adds some extra, elaborate features, but that it changes the complete application you are working on.

Sounds like horror?

Maybe this sounds like horror to you, but it can be a blessing as well. It prevents the moment where the client is proudly presented with the end product and then tells you that it is by no way what he wants.

To me it has been a good experience.

I know, I know

.. it's been too silent

Lately I have been busy with loads of stuff and hardly had the time to write some stuff here. But I have some posts in the pipeline. Promise

It will take some time though, before I can publish as a lot of things are happening.

uhm ...

I'll see you soon, I hope.

Monday, May 31, 2010

What do you get from Twitter?

.. because I don't get it

Well Lynsheila, Thanks for your question:

"Rob, what do you get from Twitter? l must be a technophobe because l dont get it, l prefer chatting face to face"
A good question

Free twitter badgeImage via Wikipedia

Well, Twitter is quite a lot and that makes it hard to grasp and hard to explain:

  • It's some sort of chat, although mostly public, eventhough you can go private
  • It's also a form of a news reader, nowadays I get more news through Twitter than through RSS feeds
  • It's blazingly fast when something happens anywhere around the world
  • I get updates from friends and see what they are up to
  • I get insight into the lifes and thoughts of famous people (sport stars, music stars etc) so they almost appear human
  • and so much more

It has to do with information flow in all sorts of ways that you can easily subscribe to and after some time you can abondan them as easy as that.

I hear and listen and also speak out through Twitter. So that is what Twitter is to me.

So, what is Twitter to you?

I dare you, come up with your explanation to Lynsheila and all the others who don't get it, but want to get it.

Reblog this post [with Zemanta]

Friday, May 21, 2010

More amazing news from Google I/O 2010

.. and some things I want

Yesterday, 21 May 2010, there was more interesting news from the Google I/O conference. Again I wish I had been there, especially since they were given away HTC EVO to each and every conference attendee. Accept to Google employees. Too bad for Matt!

Google's Matt Cutts @ PubCon 2009Image by Andy-Beal via Flickr

I should start looking for sponsors for the Google I/O 2011 ...

Maybe the big announcements were to be expected and have been predicted, still I think these again to be great news. Also I am seriously considering getting my hands on these in the near future.

Update to Android

Release 2.2 of Android, codename Froyo, is coming. It has better performance and was demonstrated too a very enthousiastic crowd.

Improvements in various areas have been made.

  • The speed has been boosted 2 to 5 times by incorporating a Just In Time (JIT) compiler.
  • It has enterprise friendly enhancements, think Microsoft Exchange.
  • Extra APIs: Application Data Backup API and a Cloud-to-Device API.
  • Tethering and Portable Hotspot, work on your laptop in connection with your mobile phone.
  • The browser has been boosted by incorporating the V8 engine. Javascript performance boosted 2 to 3 times.

My contract for my mobile phone is coming up for renewal, but I seriously consider jumping in on the Android train. It seems to be picking up more and more speed.

Google TV

Google TV is about using that little laptop screen to watching movies and your laptop and not on that beautiful great widescreen TV you have mounted on the wall. But also about browsing the web on that TV but with limited interface.

Last year I treated my family and myself on a wonderful Philips Ambi-light flatscreen HD TV. It came with Net TV. A very limited browser on the TV. There are a load of web sites pre loaded and easily chosen, but these are all put there by Philips. The companies behind the sites are paying Philips. I, as the owner of the TV, have no way of putting my own choices up there. I can choose some favorites from the available options, but that's it.

Youtube is there but typing in a search query on the remote is going back to text again and there is no way to hookup a wireless keyboard. All in all this Net TV is just not what it should be. I may have used it ten times in ten months.

Google TV brings the web to your TV, no it makes it part of your TV experience. You watch a football match on a TV channel and can have a Twitter stream in the top right corner or something. Also it promises to make the interaction with the Web much easier. Google TV can be built in into the TV or a separate box.

As my Philips receives software updates every month or so I just hope that the learn from this announcement and improve their Net TV software in my TV. I doubt it will come close to Google TV. But I have no doubts that in teh near future we will see more and more TV sets coming with better and better internet capabilities. May it be Google TV or not.

Eventhough I do try to limit the amount of boxes in my living room the day that a Google TV box comes in could be coming sooner than later.

It's over now for this year

Luckily it's only a two day event and that means not another day of big announcements. But these are only the big announcements and more smaller announcements have been made that may have more or less impact on you depending on your occupation and interests.

Now it's time to get back to work and let the dust settle and see what other competitors will come up with and how much of these things really gonna do what they look like doing.

Reblog this post [with Zemanta]