Tuesday, November 30, 2010

Marketplace advice for WP7 Windows Phone 7

This post is priceless - http://blogs.msdn.com/b/wsteele/archive/2010/10/15/important-info-for-wp7-application-developers.aspx

1) READ the docs!!!

2) Know your iconography.

3) Support Information – Test Case 5.6.

4) Toast Notification – Test Case 6.2

5) Applications Running Under a Locked Screen – Test Case 6.3

6) Back Button – Test Case 5.2.4
7) Themes – Test Case 5.1.1
8) Languages.
9) Failures upon Upload to the Marketplace
10) Windows Phone Developer Tools.

    Sunday, November 28, 2010

    Razor MVC3, a file upload form

    @using (Html.BeginForm("CreateStepUpload", "Pivot", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Fields</legend>

            <div class="editor-label">
                File:
            </div>
            <div class="editor-field">
                <input type="file" name="theFile" id="theFile" />
            </div>
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }

    Razor, MVC3 - a readonly textbox

    Code is:

    @Html.TextBoxFor(model => model.Fields[i].TheField, new { @readonly = true })

    Saturday, November 27, 2010

    Ssssshhhh - don't tell anyone but I'm enjoying web dev with ASP.Net MVC3 and Razor

    Just very impressed at the moment that my ViewModels are flying in/out of my Controllers with quite a lot of ease...

    Also impressed with how clean Razor feels compared to old ASP.Net

    Also impressed with how easy it is to extend the Expression<> based HtmlHelper code.

    ...

    A couple of things I've done that show how I'm techie enjoying myself:
    1. Enabling email verification was easy -  mainly thanks to Kevin at http://thekevincode.com/2010/09/adding-email-confirmation-to-asp-net-mvc/ 

    2. Creating enum based drop down select boxes was easy - just used http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx - then in Razor:

    @using MyExtensionsNamespace

    Some HTML

    @for (var i = 0; i < Model.MyProperty.Count; i++)
    <div>
    @Html.EnumDropDownListFor(model => model.MyProperty[i].MyEnumField)
    </div>
    }

    3. Using list collections was easy - see the snippet above - it just works when you then collect the ViewModel back in to the Controller Action method too :)

    4. Adding my own Model error was easy with ModelState.AddModelError 

    Thursday, November 25, 2010

    Getting Windows Phone 7 development working

    So I managed to borrow a Windows Phone 7 for some dev work :)
     
    I already had the basic tools installed and had been using the emulator.

    But to get the phone dev working...
    - you need to install the October 2010 update to the tools
    - you need to download and install the zune PC software (60MB download and requires reboot!)
    - you need to log on inside the zune PC software
    - you need to use the "Windows Phone Developer Registration tool" to unlock your phone

    Some more help here:

    The good news is... this all worked :) Took about 2 hours to get going, most of that spent downloading Zune stuff!

    Wednesday, November 24, 2010

    Razor outputting raw unescaped HTML.. ASP.Net MVC3

    In general I love the look and feel of the new Razor View Engine - works really well.

    However if you ever want to output raw HTML then it's a bit ugly - e.g. to output some JSON I did:

    var currentConnectionStrings = @(new HtmlString(Json.Encode(Model.ConnectionStrings)));

    It would be nice if this instead did something like @=Json.Encode(Model.ConnectionStrings) - or some other "special" character combination

    JQuery - responding to selected tab using tabselect

    If you have a standard jquery UI tabs setup:

                <div id="tabs-project">
               <ul>
               <li><a href="#tabs-project-core">Details</a></li>
               <li><a href="#tabs-project-connections">Connections</a></li>
               <li><a href="#tabs-project-alerts">Alerts</a></li>
               </ul>
               <div id="tabs-project-core">
                       etc...             
                </div>
               </div>

    And you want to determine which tab has been pressed by name (not index - because index might changed when code gets moved or if tabs get inserted..) then you can use:
     
            function getIndexOfTabAnchor(name) {
                return $("a[href*=#" + name + "]").parent().index();
            } 
            $("#tabs-project").tabs({
                select: function (event, ui) {
                    if (ui.index == getIndexOfTabAnchor('tabs-project-jobs')) {
                        // do jobs stuff...
                    }
                    else if (ui.index == getIndexOfTabAnchor('tabs-project-schedules')) {
                        // do schedules stuff...
                    }
                }
            });

    Note that getIndexOfTabAnchor() uses http://api.jquery.com/attribute-contains-selector/

    Awesome comparison of the costs and benefits of Azure versus AWS

    I've just stumbled upon this awesome analysis of some Azure versus AWS services.

    I think there are several strategic and architectural things to consider when choosing between the two services - choosing to deploy roles on Azure is an application lifestyle choice compared to choosing OS deployment and system admin on EC2 - and both lifestyles have their problems!

    There's lots of good material in here:
    http://compositecode.com/2010/11/01/cloudthrowdown-part1/

    Monday, November 22, 2010

    PivotViewer, shared images and memory problems

    I've spent a large chunk of the last weekend playing with the Silverlight PivotViewer from Microsoft.


    It's lovely!

    Despite the official upper limit on number of items being "3000", I've taken it up as high as 73000 items now - the animations don't work at that level, but the pivotviewer is very very useful there!

    You can see some screenshots (attached hopefully!) and there's also one "live" demo on http://zoom.runsaturday.com

    The only downside - there have been a few issues I've had - one of the key ones of which is:
    • if you create a .cxml collection in which items don't each have unique images (e.g. they share a default image) then the Silverlight control does something odd - it somehow seems to try to duplicate the shared images and uses up lots of CPU and memory as a result.
    This bug is reported in a bit more detail on this thread - http://forums.silverlight.net/forums/t/210211.aspx:

    To recap:

    • the bug is for collections where <Item>s share img references.
    • if I load up one of these collections in the standalone viewer these work fine
      - the load is smooth and the memory use is expected.
    • if I load up the same collection in the silverlight pivotviewer then the items with shared images
      take a long time to display (they pop into the display one by one) and the memory use is higher
      - it increases with each image loaded.

    You can just about see this effect if you watch the swimmer icons when you first load up:

    The effect is really really noticable when you get to larger data sets

    Sunday, November 21, 2010

    Numpty Silverlight DataBinding continues....

    So if you are doing Silverlight or WPF and you're trying to do MVVM... and you sit there wondering why your ObservableCollection<T> just isn't working...

    ... then consider it might just be....

    ... because you are an idiot and you declared your code:

    public ObservableCollection MyCollection;

    when it should of course have been...

    public ObservableCollection MyCollection {get;set;}

    Arggggggggggggggh! Serves me right for coding on Sunday night! 

    Some hacky fixes to PAuthor PivotViewer library

    Overall the PAuthor project for creating PivotViewer for Silveright datasets works great - I've used in in .Net4 for 4 separate command line apps :)

    However, when working on some large data sets (around 75000 Items) I found the following problems - mostly to do with corrupt items in my input.

    Hope this post helps other people...

    Problems seen in collectionCreator.Create(m_dziPaths, m_dzcPath); in ParallelDeepZoomCreator.cs

    • System.ArgumentException in ParallelDeepZoomCreator.cs due to problems in my item names (some of my names included the "*" wildcard character - doh!
    • And System.IO.FileNotFoundException in ParallelDeepZoomCreator.cs due to unknown problem (no real clue why these particular folders didn't exist - it was 8 out of 75000...)

    To fix these I just wrapped the call with: 

                 List<String> toRemove = new List<string>();             foreach (var c in m_dziPaths)             {                 try                 {                     System.Security.Permissions.FileIOPermission f = new System.Security.Permissions.FileIOPermission(                             System.Security.Permissions.FileIOPermissionAccess.AllAccess, c);                 }                 catch (ArgumentException exc)                 {                     toRemove.Add(c);                     System.Diagnostics.Trace.WriteLine("INVALID PATH " + c);                 }             }             foreach (var c in toRemove)             {                 m_dziPaths.Remove(c);             }              while (true)             {                 try                 {                     DZ.CollectionCreator collectionCreator = new DZ.CollectionCreator();                     collectionCreator.Create(m_dziPaths, m_dzcPath);                     break;                 }                 catch (System.IO.FileNotFoundException exc)                 {                     System.Diagnostics.Trace.WriteLine("STUART - SORRY - REMOVING " + exc.FileName);                     m_dziPaths.Remove(exc.FileName);                 }             } 


    Some multithreaded problem seen in image download

    The finalizer for PivotImage.cs occasionally sees IO exceptions in the File.Delete operation - the exception claims that the fie is currently open in another process.

    Not sure what is causing this - my guess is it's a multithreading issue of some description.

    To fix (mask) this I simple added a try catch to the finalizer:


            ~PivotImage()         {             if (m_shouldDelete == false) return;             if (File.Exists(m_sourcePath) == false) return;              try             {                 File.Delete(m_sourcePath);             }             catch (IOException)             {                 System.Diagnostics.Trace.WriteLine("Some clean up needed " + m_sourcePath);             }         } 

    That's it - hope it helps someone.

    Saturday, November 20, 2010

    Using the Silverlight PivotViewer Control and seeing NotFound when deployed on IIS

    If you build and test your lovely new PivotViewer SL app and then when
    you deploy to a full IIS server you see "NotFound" reported for your
    collection, then...

    Make sure you've set the mimetype for .cxml, .dzi, .dzc all as
    text/xml within IIS for your current website.

    Worked for me :)

    Helpful suggestion found on :
    http://forums.silverlight.net/forums/p/194861/452655.aspx

    Friday, November 19, 2010

    Silverlight compressed binary serialization

    So... I did my first Silverlight app - very good fun (although there was a fair amount of head scratching too!)

    As part of this app I needed to send some fairly chunky bits of data to the client. To do this I used http://whydoidoit.com/silverlight-serializer/ and http://slsharpziplib.codeplex.com/

    On the server (in an offline process) the code that generated my compressed files looked like:

                using (var f = File.Create(zipFileName))
                {
                    using (var zipOut = new ZipOutputStream(f))
                    {
                        ZipEntry entry = new ZipEntry("stuff");
                        var toStore = Serialization.SilverlightSerializer.Serialize(myClass);
                        entry.DateTime = DateTime.Now;
                        entry.Size = toStore.Length;
                        zipOut.PutNextEntry(entry);
                        zipOut.Write(toStore, 0, toStore.Length);
                        zipOut.Finish();
                        zipOut.Close();
                    }
                }

    And in the Silverlight client the code looked like:

            public void LoadFrom(Uri url)
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                request.BeginGetResponse(new AsyncCallback(ReadCallback), request);
            }

            private void ReadCallback(IAsyncResult asynchronousResult)
            {
                HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
                using (ZipInputStream zipIn = new ZipInputStream(response.GetResponseStream()))
                {
                    ZipEntry entry;
                    if ((entry = zipIn.GetNextEntry()) != null)
                    {
                        var myClass = Serialization.SilverlightSerializer.Deserialize<TheClass>(zipIn);
                        if (myClass == null)
                        {
                            MessageBox.Show("Some error has occurred - unable to read data - sorry!");
                            return;
                        }

                        Dispatcher.BeginInvoke(() =>
                            {
                               // do stuff with myClass here
                            });
                    }
                }
            }

    It all worked surprisingly well :)

    Thursday, November 18, 2010

    More problems with SQL Azure backup


    you can backup SQL Azure using
    CREATE DATABASE [newName] *BUG HERE* COPY OF [oldName]

    However, recently I've just hit lots of problems with doing this on "The CREATE DATABASE statement must be the only statement in the batch."

    Sadly I don't seem to be able to get past this... I think it's something to do with names? Certainly it's an odd (and probably misleading) message... Anyways... I'll use the other backup method instead...

    NEWSFLASH!!!!
    The problem was my typo...

    The statement is not:
    CREATE DATABASE [newName] COPY OF [oldName]

    Instead it is:
    CREATE DATABASE [newName] AS COPY OF [oldName]

    Doh! (although top marks to SQL Azure for the error message)

    Tuesday, November 16, 2010

    A look at some Silverlight control libraries

    As I start serious Silverlight development for the first time, I've been looking at and evaluating some of the control libraries out there.

    Why? Well, because they contain huge amounts of slick, useful, QA'd functionality which will accelerate my development - so they represent superb *value* for money.

    Here are some of my notes so far:
    • Telerik - have a huge set of controls including rich text editing, super framework libraries (like containers and transitions), and lots and lots of charting. I've attended a couple of their webinars and clearly they've got good functionality now, plus lots more coming every quarter.
    • Infragistics - a fairly large set of functionality again including grids, menus and a docking framework
    • Dundas - seems to be mainly focussed on Business Intelligence (BI) dashboards - so lots of charts.
    • Actipro - a much smaller set of functionality focussed around an MsDev like code editor.
    So far... I'm tempted to buy Telerik with the intention of using:
    - the charting - especially the lovely sparklines :)
    - the grid - everyone needs one eventually!
    - the overall framework stuff - especially as they use MVVM everywhere.

    I will install the trial version soon and then come back with more feedback.

    Tuesday, November 02, 2010

    Serialising Enums with Newtonsoft JSON.Net

    For a while... I was using this serializer:

    public class JsonEnumConverter<T> : JsonConverter
    {
    public override bool CanConvert(Type objectType)
    {
    return objectType == typeof(T);
    }

    public override void WriteJson(JsonWriter writer, object
    value, JsonSerializer serializer)
    {
    writer.WriteValue(((T)value).ToString());
    }

    public override object ReadJson(JsonReader reader, Type
    objectType, object existingValue, JsonSerializer serializer)
    {
    return Enum.Parse(typeof(T), reader.Value.ToString());
    }
    }

    This allowed me to serialize/deserialize using attributes like:

    [JsonObject]
    public class MyClass
    {
    [JsonConverter(typeof(SerializationUtils.JsonEnumConverter<DateTimeTestFormat>))]
    public DateTimeTestFormat DateTimeTestFormat { get; set; }
    }

    However, eventually I worked out that I could just use a more general
    solution - and that I could pass that in to the top-level JsonConvert
    methods:

    public class GeneralJsonEnumConverter : JsonConverter
    {
    public override bool CanConvert(Type objectType)
    {
    return objectType.IsEnum;
    }

    public override void WriteJson(JsonWriter writer, object
    value, JsonSerializer serializer)
    {
    writer.WriteValue(value.ToString());
    }

    public override object ReadJson(JsonReader reader, Type
    objectType, object existingValue, JsonSerializer serializer)
    {
    return Enum.Parse(objectType, reader.Value.ToString());
    }
    }

    Much easier... :)

    Monday, November 01, 2010

    Some practical experience of GPS battery life for Sports Tracking apps

    On Navmi/RunSat, I got asked:

    >> What's the impact on the battery when doing frequent GPS resolutions?

    The answer is battery life varies dependent on phone...

    On an iPhone you have to really mess about to improve battery life -
    the only way of doing it on older phones is to start playing out audio
    (e.g. a playlist) - then you can turn the screen off but still keep
    your app alive and capturing GPS.

    On my WM6.5 Omnia II, it's easy to keep the app/GPS alive but to save
    some power. If I do that and still monitor the GPS, then up to 6 hours
    battery life is OK - so pretty good.

    On a Bada Wave, there's a SYSTEM_SERVICE level call to make so that
    the app can carries on even when the screen is off - locked I can
    manage 3-4 hours easy - not tried any longer yet - but suspect 6 is
    about the current limit.

    On my Nokia 5800, it seems that the Nokia ST app managed 2-3 hours OK
    - not tried it any longer.

    On Android, it's too early for me to say - but I know that the Google
    MyTracks app can manage long sessions - 6 hours+ - although they do
    have some sample-rate dropping code to do that - basically it depends
    what your activity is:
    - if you're walking, then you can probably get away with sampling only
    every few minutes
    - but if you ever want to do turn-by-turn directions in a car, then
    you'll need to up the sampling rate to something much more frequent.