Compsoft Flexible Specialists

Compsoft plc

Compsoft Weblog Compsoft Website News Archive Privacy Policy Contact Us  

Thursday, April 08, 2010

iPad, Glorious iPad

Shipped from the USA, our iPad has been in the office for 27 hours or so... well, nearly. The MD took it to a meeting yesterday afternoon and then home and played in to the small hours with it. And now it has gone to another meeting. Interestingly, the meeting yesterday was about the development of an Android phone app, but that quickly got forgotten as the iPad stole the limelight.

I had the pleasure of spending some time with it this morning, looking over it with colleagues and have received a variety of opinions:

The Sales Team: they loved it. It is a tactile thing that wants to be used, to be touched, to be seen. They can see that putting it in front of customers with their iPhone / iPad app on will blow them away. I guess the telling sign is that all bar none have expressed their desire to get hold of an iPad.

The Support Team: the only comment required is that as I left the Head of Support was on the phone to his wife, currently on business in the USA, asking her to get to an Apple Store! (Update: she is on a waiting list!) (Update #2: Wife was able to pick up 64GB iPad; Head of Support uncontrollably happy!).

Design Team: in spite of expressed concerns our Senior Designer 'loves it'. The slickness of the interface has impressed him, and he too sees how clients will love seeing their imagery in a fresh crisp view. He was exploring how he could justify to his wife the purchase!

Development Team: it shouldn't surprise that their view focused on its gaming potential - the additional control that the larger surface offers over the much smaller iPhone was evident as a Senior Developer demolished a tower in 'Angry Birds'. When questioned, the dev team confirmed that they would rather build for iPhone / iPad (iPad using a similar development framework to iPhone) than for other mobile platforms.

The client: I took the liberty of introducing a long-standing client to the iPad; his reaction used colourful language to illustrate his surprise at its ease of use and its capabilities.

The girls next door: It's a gadget, a boy thing... really? They were the first to want to touch the screen and flick through pages on the book reader. Mind you the guys from next door were impressed with the comic book reader.

My considered opinion:

This is a great gadget. For viewing websites, ebooks, documents, videos (the on board speaker is pretty good, not great but adequate) and photographs, it is revolutionary. It doesn't have a Flash player, which means media on the BBC website is not viewable (yet?), but the experience of viewing the news pages is great. Really great. In educational situations, I think this may well transform revision - one app that looks at the Periodic Table is phenominal. It is a delight to look at and to use!

Do I see this becoming a business tool? Absolutely. We previously built an iPhone app that presents a host of videos; our dev team converted this for use on the iPad and, wow, it is very impressive. OK, so this app is an instructional tool for a golf tutor, however, the stunning presentation can be applied for use by sales teams, project management ... anyone! For example, in my marketing capacity I can see already how easy potential customers will be able to view a range of documents and supporting videos.

We have an internal app that has an interface on the iPhone. We currently can edit info from the iPhone, however, the touch screen keyboard is not a practical size, comments added, therefore, consist of only a few words. With the iPad and its more capable screen size, it is much easier to type meaning that greater amounts of information will be included. Actually, the word processing app works well; it enables one to add text naturally unlike with the iPhone, and certainly unlike other smartphone devices.

It is because of the combination of these that I think it will become a valuable business tool; it works as a presentation medium, as a document viewer and as a means to capture textual information. And it is fun.
So, perhaps the caveat is that the iPad is going to work well for businesses, provided the right apps exist.

My challenge is now to convince the wife that it is a good idea of hers for us to get one...

Labels: , ,

Tuesday, May 05, 2009

Making sure your application is not left in debug="true"

You will find loads of articles around the web reminding us all that running your production ASP.NET website in complication debug=true mode is a BAD THING!
To make sure we avoid this problem we have added a start up check in our application that will make sure that the build mode (debug or release) of our binaries match that of the web.config. As all releases are done via our build server all our binaries will be in release mode. However we tend to make major changes to the web.config on the live servers so deploying the web.config is usually not an option.

To check if the web.config has debug enabled you can use HttpContext.Current.IsDebuggingEnabled.

To check what mode a binary is in, we use the #DEBUG Preprocessor Directive:

   1: // codesnippet:ADB0358E-3BD1-11DE-B2D2-764056D89593
   2: public static BuildModeEnum BuildMode
   3: {    
   4:     get    
   5:     {        
   6:         #if (DEBUG)
   7:             return BuildModeEnum.Debug;
   8:         #else
   9:             return BuildModeEnum.Release;
  10:         #endif
  11:     }
  12: }




Labels: , , ,

Monday, February 23, 2009

Vagaries of geocoding a postcode

Plotting 'lat lngs' on a map is a fairly straight forward task. Especially doing it on a Google map.

Using a .NET implementation of a Google map is nice and easy. Doing it with PHP and javaScript is a bit more of a work up, but perhaps more satisfying when you get dirty and use some of the natty little Google features available.

However, in the course of writing a site for a Letting agent [www.batterseaflats.com] I came across an unexpected result when geocoding via HTTP with Google.

To make the site really easy to administrate details of properties I thought it would be nice to have a field containing the property's postcode, and during the save process, geocode up the postcode to get a nice 'lat lng' to show on a map. Of course I based the expected result on the performance of locating a postcode via Google's own maps.google.co.uk interface, which is nice and accurate.

Unfortunately, I often ended up with addresses that weren't quite in the right place. Much as I like Germany, I was quite sure I shouldn't be displaying properties outside of London!

I switched to using the GClientGeocoder Google object, but it still wasn't accurate enough. (Consider having four or five properties in the same street to advertise, you really want them to be in the right place on the street).

So I thought I'd let the user geocode an address string (because flats are sometimes in blocks with a name that can cause problems trying to guess what the user has typed in), then allow them to move the point around on the map. A simple feature, which the client really liked!

Use GClientGeocoder to get location:

function locateAddress(address) {

geocoder.getLatLng(

address,

function(point) {

if (!point) {

alert(address + " not found");

} else {

showPoint(point);

}

});

}


When creating the marker on the map, enable the 'draggable' GMarker property:

var marker = new GMarker(point, { icon: iconAvailable, draggable: true, dragCrossmove: true });


and listen for the marker's 'dragend' and capture the new location:

GEvent.addListener(marker, "dragend", function(latlng) {

captureLatLng(latlng);

});


And when displaying the list of properties, go crazy by synchronising the mouse hovering on the sidebar list of entries with the markers by adding a Event Listeners for 'mouseover' and 'mouseout' switching the styles as needed:

GEvent.addDomListener(div, 'mouseover', function() {

div.className = 'sideHighlight';

marker.setImage('images/highlightHouse.png');

});

GEvent.addDomListener(div, 'mouseout', function() {

div.className = 'sideNormal';

marker.setImage('images/house.png');

});



Details of the Battersea Flats project can be found here: http://www.compsoft.co.uk/Portfolio_Battersea_Flats

Labels: , , , , , , ,

Thursday, February 12, 2009

Empty UpdatePanels add a blank line after callback in IE

We hit a bug the other day where we found that UpdatePanels misbehave somewhat in Internet Explorer.

We spotted it because we always have an area at the top of our pages for displaying error messages. (You can see an example of this if you go to our Contact Us page and click "Send Message" without filling in your contact details.)

If you did a callback to the page that didn't result in any errors, the UpdatePanel around the error box would remain empty. Thus in most browsers you wouldn't see anything happen at the top of the page.

However, IE would insert a blank line where the UpdatePanel was, bumping the rest of the page content down by 12 pixels or so.

This is supremely annoying as it can really throw out the design of your site. It turns out it happens even if there elements in the UpdatePanel, if they're elements that don't render anything visible on the page (empty spans, hidden input controls, etc.).

Now, one way to fix it is to set the RenderMode of the UpdatePanel to Inline. This stops the bug in IE, but it also makes the UpdatePanel render as a span instead of a div. This is no good for us because the error box (when it renders) is a div, and nesting a div inside a span is invalid html.

So here's the solution we came up with - I hope it's useful to you too!

We created a class that inherits from UpdatePanel, but overrides how it renders, adding a style of display:inline if it's rendering as a div. So now it's still a div (and so it's valid to nest div within it), but it renders inline as a span would, thus sidestepping the IE bug.

Also, as it inherits directly from UpdatePanel, we can use <Compsoft:UpdatePanel> everywhere that we'd use <asp:UpdatePanel>. It's fire-and-forget: it behaves exactly like an UpdatePanel, except without the problems.

public class UpdatePanel : UpdatePanel
{
  protected override void RenderChildren(HtmlTextWriter writer)
  {
    // IsInPartialRendering is a reliable way of
    // telling it's a callback
    if (!this.IsInPartialRendering &&
      this.RenderMode == UpdatePanelRenderMode.Block)
    {
      StringBuilder sb = new StringBuilder();
      base.RenderChildren(new HtmlTextWriter(
        new StringWriter(sb)));

      string renderedHtml = sb.ToString();

      if (!renderedHtml.StartsWith("<div "))
        // This should never happen; better safe than sorry
        throw new Exception(
          "An UpdatePanel with a RenderMode of Block "
          + "isn't rendering as a <div>");

        writer.Write("<div style=\"display:inline\"");
        writer.Write(renderedHtml.Substring(4));
    }
    else
      base.RenderChildren(writer);
  }
}

Labels: , , , , , , , ,

Tuesday, November 11, 2008

Tim Jeanes: TechEd 2008 - Day 2

WUX202 - Building Rich Internet Applications Using Silverlight 2

I've fallen a bit behind on the Silverlight front, so it's great to take this opportunity to catch up a bit. This was a fairly low-level session to get you up and running, but without skipping over the details.

We were taken through setting up a Silverlight application, creating and (fairly radically) styling some controls, retrieving data from a web service, creating business objects from that data and then displaying it.

I can't think there's many times I'd want a slowly rotating text box whose background is playing one video, whilst the interior of each (multi-alphabet) character contains part of another video, but it's nice to know that you can.

One thing I was really pleased to see was quite how feasible it was to develop Silverlight by typing the xaml directly. I've only seen it generated in blend before, but I prefer the feel of the fine control you get from typing it yourself - I generate all my html that way for precisely the same reason. I suspected it would be too onerous to be practical, but was glad to see that it really wasn't.

Data access in Silverlight is really easy: it all works by calling web services, and using .NET's XDocument and XElement classes, converting the XML text to objects is a doddle. Web services can be called from the same site as where the Silverlight is being hosted, or, by negotiating a SilverLight policy file, from an external domain.

Creating reusable controls in Silverlight is just as easy as in ASP.NET, and data can be passed to them just by setting their DataContext property. In many cases that's all you have to do in the code behind, and the xaml will pick up the data and display it accordingly.

I deliberately avoided Silverlight 1, and I'm glad I did. Silverlight 2 has dozens more controls available to you in its core libraries, and a whole bunch more - mostly the more advanced ones such a DataGrids - that can be included by namespace. The neat thing is that if you don't use those namespaces, they aren't included in the the download, giving less of an impact on your user. Microsoft plan to release more control toolkits in future.

The argument they gave us for the lack of controls in version 1 was that you should design your own; it's nice that those of us with little artistic talent can throw the standard controls into our applications, but also that they're all completely re-stylable by applying templates.

Databinding works a lot like in ASP.NET, but with the additional power of 2-way binding, whereby data entered by the user automatically immediately changes the properties on your objects.

All in all, I'm looking forward to getting involved in some Silverlight development. Much of what I know of ASP.NET will be transferrable, but we'll also be spared the pain of trying to get a decent layout using css.


ARC205 - How IT will change in the next 10 years and why you should care

I thought the content of this talk would be similar to talks I've seen at the last two TechEds: long term projections about where software development will be going in the next decade. But no - one tenth of "the next decade" has already past since last year; nearly a quarter since the year before.

IT is undoubtedly a fast-moving industry, and I've often wondered what my job will look like when I'm 60; or even if I'll still have one. How will I keep up with the industry as it moves? How can I know if it's even possible when there aren't any 60-year-old software developers yet?

The key really is keep at the bleeding edge. IBM crashed and burned because they had a cash cow (the mainframe), and made the mistake of treating it as a sacred cow. The technology we rely on today can (and will) be obsolete soon after you get comfortable with it.

An interesting graph (I'll link to it when the slides from the session are published) showed the relationship between cost, risk, availibility and value as technology moves through the phases of being a future technology, emerging technology, widely applied and obsolete. We're running on a treadmill and you never want to get too close to the back. I think this is something we do well at Compsoft: we're always looking ahead and keeping abreast of what the next big thing will be, adopting it right as soon as it becomes available.

We covered quite a bit of how we'll not only treat software as a service, but treat hardware as a service too. With more and more processing being offloaded to the cloud, we don't expect most companies to have their own server room a few years from now. The car/ taxi analogy works well: if you're buying a car, you care about the make, the model, the colour, the tyres, etc.; if you're catching a cab you only care about how clean it is, how dodgy the driver looks, and how much they're going to charge you.

Expect to see some legislation coming in for IT services soon though - we're pretty much the only public service at the moment that isn't regulated; and also probably the fastest-growing one.

Some interesting international statistics and predictions came out. Nigeria's most profitable export is oil; its second is internet scams. Every year the US produces 100,000 new software engineers; China produces 500,000 (and that's if you only count the ones who can speak English). Iceland's data centre industry will be booming shortly: IT currently produces as much carbon as aviation and we need to radically cut back on our power consumption. We need cold, remote places with cheap electricity; Iceland has this, along with the fattest of pipes to America and Europe.


WUX307 - Developing Accessible Web Experiences With Silverlight

Like last year, the seminar on accessibility was poorly-attended, and with a lot people dropping out before the session ended. I guess it's just not a sexy topic, and unless you have a customer who particularly cares about it, you're likely to have a zero budget to implement any accessibility whatsoever. Ah well.

We covered some basic principles of making websites accessible. This applies to everything, not just Silverlight. The WCAG guidelines give some useful pointers about accessibility: everything should be perceivable (with low, colour-blind or no vision); everything should be operable (the keyboard should be the only tool you need); everything should be understandable (clear, readable, predictable layouts, and forgiving of mistakes such as miss-clicks); everything should be robust (we should assume as little as possible about the technology used by the end user.

We got to see a little more of ARIA (Accessible Rich Internet Applications) in this session. This adds a whole bunch of attributes to standard html that is respected by assisted technology (AT) for people with disabilities. Thsi basically lets you write less semantic html to produce all the nice effects your fully-able users want, but add the attributes that ensures it's still accessible.

For example, the tabindex attribute is now available on all elements, with the addtional support of tabindex="0" to let the browser decide the order, and tabindex as a negative value for items that shouldn't be accessible via the keyboard but that can be set programatically.

Also the role attribute lets you give a lot of information about what an html element is actually for - you can give your div a role of banner, navigation, main, etc., for example.

Setting live regions in your html lets AT know that these are parts of the page that will change dynamically. You get some pretty fine control over how sensitive it is to change, and even how the AT should announce that the region has changed (the settings are "polite", "assertive" and "rude").

I expected accessibility in Silverlight to be more painful that in html, but actually it opens a whole of new opportunities. As Silverlight is so media-rich, you can easily add your own subtitles to videos, as well as sign language options. Users can change the size of captions, turn additional descriptions on and off, etc. You really get to make the experience for disabled users as exciting and as varied as it is for everyone else.

The AutomationProperties class lets you add attributes such as name, help text, accelerator keys, etc. to pretty much any element, for use by AT devices.

Another nice feature is that Silverlight can detect that the user has set their browser to High Contrast mode, meaning we can automatically switch the Silverlight component to use a more clearly visible theme.

Media files support media markers that can trigger events code-side, so you can handle them however you want. We saw a demo of extended descriptions, where (if the user had turned them on) the video would pause, provide an audio description of what was happening, and then continue from where it left off.

There's still room for improvement: Silverlight doesn't yet support two videos playing in sync, so if the user's on a slow connection the sign language may get out of sync with the main video. However, as you can change the video stream being played dynamically, it's feasible to swap between one video with signing and one without, seamlessly whilst the video's playing.

The Silverlight demo (which showcases a whole bunch of best practices for accessibility) is available on CodePlex - look for AMP (Accessible Media Player).


WUX305 - ASP.NET MVC Practices

I've been resolutely avoiding MVC for the last year, waiting for it to settle down, iron some of its problems out, and then decide if I like it or not.

Well, it's done a fair bit of ironing, but I'm not entirely convinced that I like what I see.

On the one hand, I just LOVE the testability of the MVC paradigm. In this session we saw how tidily it integrates with Inversion Of Control and purity of the code that you get as a result.

On the downside, the html you write has bits of code littered through it, which is proper filthy dirty as far as I'm concerned. Hadi's argument in this session was that your view should have no logic in it, so the code in your page is going to minimal, so that little bit of dirt is just fine. Hmm... I don't know...

What we got to see today showed us a whole lot of how to implement a nice-looking, AJAX enabled, error-handling, fully testable MVC application. I'd like to have one of those, but getting there would just be such a hell of a lot of work.

The trouble is that we've invested a whole lot of effort ensuring that developing applications at Compsoft takes as little effort as possible. To edit a record, you barely have to write more than the properties you want to edit, and you get all the right controls for the datatypes, full error-checking, etc. right out of the box. Searching, listing, pageable repeaters, building up complex records without saving anything to the database - we can do it all in minutes. Unfortunately we do it all using the technology we have available: we use web forms, web controls, update panels, the view state - everything you lose if you switch to MVC.

So switching to MVC would be great because our code would be cleaner, purer, (in theory) more maintainable, more swappable; the problem is that we'd have to throw away most of the last year or two's investment in our reusable web controls.

Though today I saw a vision of how I would like to rewrite our reusable code libraries to work on MVC, it's not a few tweaks to upgrade it, but rather a total re-write.

Roy, can I have a while to do this? I reckon about three or four months solid work should be enough to get us back to a point indistinguishable from where we now, except for a warmer glow within. Thanks.


WUX306 - Silverlight 2 Security End-to-End

Silverlight has security built in at a pretty fundamental level. All Silverlight applications are sandboxed and so can't touch anything else on the client machine - not even other Silverlight applications.

However, the Silverlight plugin that the user has installed does have acces to their hard disk. Not all of it - it can store persistent data up to a limited volume. By default it's 1MB per site, but you can cause the application to request more storage capacity from the user. The store can be unique to each Silverlight app, or shared by the applications on a single site if you prefer.

This data can be accessed via the IsolatedStorage class. At its simplest it contains a dictionary of name value pairs, though you can also use it as a virtual file store where you can create folders and files of any kind.

Whenever a Silverlight application needs some data from the outside world, it's going to be getting that via web services. The web services you call are limited: you can always call webservices on the same point of origin as the original application (to the domain, sub domain, port and protocol).

That's sufficient for when you're developing your own self-contained Silverlight system, but you can also expose public services to other Silverlight applications. Out of the box, cross-domain web service calls aren't allowed. However, the server can opt in by having a file called clientaccesspolicy.xml in its route directory. This contains information about which Silverlight applications can call the web service, by domain name, with wildcards. For ease of upgrade, Silverlight also supports the existing Flash version of this file.

You have to make sure you disable any caching on this file, and you can't use any redirects.

As with web sites, these web services are susceptible to cross-site request forgery attacks, so you need to include a token both in the cookies for the site and the request itself. Also, if you have a service that's used both by your local application and also exposed publically, it's best to keep the service and the application in separate subdomains, so that cookies from your site don't inadvertently get included in requests from other Silverlight applications in the same browser session.

Labels: , , , , , , , , , , , ,

Richard Thomason: TechEd 2008 Day 2

3 Oslo, Dublin and WF4 - David Chappell

Not the ex-Compsoft employee David Chappell, instead a rather annoying "gee dub-f" Seattle microsoftie.

This session promised a rewrite of the Workflow foundation. I went to a couple of sessions on WF3 last year and Tim investigated it for Hippo, and both of us found it to be inadequate. The hope is that the new version may be more up to scratch.

As it turns out, there has been a lot of work done. The workflow engine got a rewrite and is "much faster". They added a Flowchart model in addition to the Sequential and StateMachine ones. To help people who are afraid to write their own host process (?) sic, Dublin provides something like a service host for WF activities, including start/stop/restart and persistence. WF is the sort of thing you would use with SharePoint to implement simple activities beyond the scope of form-filling. Comparisons with Biztalk are probably not useful. Biztalk is not free.

Latterly, David spoke about Oslo, which is a general purpose modelling platform; here's an url for you to look at:

http://www.microsoft.com/soa/products/oslo.aspx.

Unfortunately, my BLX detector was activated during this part of the talk, and when he started talking about modelling schema languages and first releases, it triggered the "bail out now before the Tourette's kicks in" alarm.


4 Developing data centric web applications - Jonathan Carter

This session demonstrated substituting DynamicData controls for normally bound ones using templates to reduce the amount of code in asp forms. I can't resist saying that these are features that have been in Equinox since version 1 :) but enough of that since we didn't do forms in the web server, yet. There is a large amount of work to set up the template and refer to it in the form, however it is work that needs doing only once, and is extensible with user-defined types and so on. This does look good, especially for new, more substantial applications, but it still gives me the "whole load of legwork" feeling, and I don't see the point of reverse engineering it into existing apps. Maybe my expectations are too high.

5 Developing accessible web apps with Silverlight- Sean Hayes

Well it was either this or Windows for Washing Machines. I was concerned to see that the "with Silverlight" part of the title was missing from the title slide, but I thought I'd stick it out to see what I could learn. Sean rehearsed the well-known accessibility feaures in standard HTML - alt text and so forth, then went on to describe ARIA, which extends accessibility features in the latest browsers now, and will be part of HTML 5. It provides assistance in more complex controls such as drop-down lists and slider controls, etc, as well as a "live region" feature that allows assistive technology to handle dynamically updating areas of the screen.

Silverlight 2.0 is fully enabled for accessibility, and in this repect is unlike most modern browser-based implementations. Audio have have transcripts, and video can have captions or subtitles, as well or instead of transacripts. Finally you can use descriptions, which can pause the video if necessary. PC media allows for sign language translation more easily, since unlike TV it can be switched off and on.

6 LINQ and C# - Luke Hoban

This session is a warm-up for tomorrow's dead exciting LINQ to Anything talk, to remind me of the deep details of LINQ in C#.

LINQ works with both objects (via an enumerator interface) and via SQL (via a query interface). It's the same deal for both, and only varies in the provider and the references, eg Customer object versus db.Customer data provider, and so on. Luke showed a simple example querying customers:

var query = from c in LoadCustomers() where c.city == "London" select c;
var query = LoadCustomers().where(c => c.city == "London");

He demonstrated the .Net Reflector tool which shows details of generated code. CachedAnonymousDelegates turn lambdas into references to private static methods. If static methods start with "this", it defines an extension method that can be used with dot notation. He then overrode the Where method ("yield return" adds item into the output collection) on IEnumerable, which only executes as much as it needs to get to the next element, then returns that.

He then showed a SQL version demonstrating expression trees, which showed how out of memory execution works. Lambda expressions can also be turned into expression trees:

Expression<Func<Customer, bool>> MyExpr = c => c.City == "London";

IQueryable is equivalent to IEnumerable for out of memory types. It contains a pointer to an expression tree, and a Provider which can executes the query. The Provider needs to traverse the expression tree and provide results for resolvable items.

7 Using multicore resources with the concurrency runtime - Joe Duffy

Anything that makes it easier to do multi-thread programming is worth checking out. This was a brain melting discussion of how Windows native and the CLR do thread pooling and task allocation. There are two separate systems which mirror each other. The Concurrency runtime will ship with VS 2010.

The CTO of Intel said last February that he believes we'll have 80 cores in our pc's within the next decade. Secondly although Moore's law is not broken for numbers of transistors available, the fact is that the increase is not going to lead to an increase in speed as it has done in the past, so therefore in order to speed things up we will need to be looking at more concurrency.

The main technique of interest Joe discussed was task stealing, which gives much better performance in highly parallelised processes where threads create tasks recursively. The way it works is that threads can push and pop tasks on their local FIFO queue without locking (except the first one), and if other threads run out of work, rather than wait idly they can lock and pop other queues on a LIFO basis, thus maximising throughput.

Labels: , , , , , , , , , , , , , , ,