What we did on our holidays: a classic guitar, an iPad, Fender and iRig

This post is somewhere near the border of being off-topic but I consider it geeky enough myself to share it here.

Like many others of my generation, living their high-school day in the end of the sixties/ beginning seventies, I’m a guitar kid. Despite my heroes like Hooker and Hendrix I never had more myself than a nylon stringed Spanish instrument. And love that. This holiday I tried to bridge some gaps using today’s technology.

There are wonderful apps for an iPad like Amplitube which emulates classical Fender guitar amps, complete with distortion and the like. Using an iRig you can plug an electric guitar straight into your iPad (or iPhone). A pickup does not work on a nylon strings (no, don’t get me started on Takamine) but I did have an old Aria (a brand known over here mainly for its recorders) contact microphone. The output level of a (contact) microphone is less than that of an electric guitar, but perhaps it could work with an iRig. Googling around brought up a lot of ways to build your own contact microphone (on Youtube) but no answer to my question. So I went to a real life music shop (Westerhaven in Groningen). They shared my doubt but offered to give it a try. In case it wouldn’t work I could just return the iRig. Where do you find that in a web-shop ?

And I’m going to keep it, it does work ! This is my setup:

iRig

The signal is weak, just raise the input level in Amplitube’s settings.

Level

Of course the sound does not have the electric punch. The level of noise is acceptable with the noise filter switched off. In most settings switching that on filters out to much of the tones as well.  The tremolo of a Fender Twin is not as deep as I had hoped. But the Super-Sonic really let’s the Christmas blues scream out.

That’s it, a nice combination of classic old stuff and new technology. I’m looking forward what surprises 2012 will bring. Happy new year !

Posted in Uncategorized | 4 Comments

Telerik components for asp.net: learning to live with RADical family. (On using radScheduler in an MVC app)

Telerik is a Friend of codebetter and they deserve some more attention. In this post I will explore some of my recent experiences with their components for asp.net. There are two suites of them. On the MVC one I can be short. The components work very well and have a fluent api which fits very well in asp.net MVC. Both user and developer will be quite satisfied. On the Telerik site is a set of live demo’s which tells all far better than I can do here.

Just one code snippet to draw your attention.

@using Telerik.Web.Mvc.UI

@model int

<div id=”dbcDiv”>

@(Html.Telerik().TabStrip().Name(“DBCs”)

    .Items(tabs =>

               {

                   tabs.Add().Text(“Status”).LoadContentFrom(“DBCStatus”, “ZorgTraject”, new {idDBC = Model});

                   tabs.Add().Text(“Activiteiten”).LoadContentFrom(“Activiteiten”, “ZorgTraject”, new {idDBC = Model});

                   tabs.Add().Text(“Centen”).LoadContentFrom(“Afleiding”, “ZorgTraject”, new {idDBC = Model});

               }

           )

    .SelectedIndex(0)

)

</div>

 

This results in a tabstrip where the content is loaded on demand from controller actions. It speaks for itself for anyone working with MVC.

The Telerik AJAX library deserves some more attention. Nearly, but not all, of its controls have counterparts in the MVC library. The claim is that the AJAX controls do work on MVC pages, with some small restrictions. We needed the scheduler, a control for planning appointments. Appointments with many resources like workers, visitors, budgets and so on. The scheduler has only an AJAX version. In the remaining of this post I will demonstrate how we got it to work and enriched it’s possibilities using MVC components.

The controls in the Ajax library are named RAD controls. Some years ago RAD was a flaming topic on Codebetter. I don’t want to drag old cows from the ditch but do like to kick against some thighs occasionally. You can use either a Dutch sayings book or your own imagination to find out what that means. Yes, you will find quite some spaghetti drag and drop code when googling around on RADcontrols. No, here I only wanted to tickle your attention.

An MVC page for the RadScheduler

There are some restrictions on using the RAD-scheduler on an MVC page .

  • Use the aspx ViewEngine. The Razor view engine does not understand the Telerik (or any other custom) tags. The good thing is that you can use ascx partial views on a Razor page. The bad thing is that you cannot use Razor views on an aspx page. All Telerik demo’s are presented using both view engines.
  • The page should include a form which runs server side. This can be a problem which we will meet later in the custom form.
  • The scheduler should run “web-service” mode. That is it gets all it’s data from an (AJAX) web-service. This is good for the user-experience but knocks out the complete server side api of the scheduler. Most server side events do have a client side (JavaScript) counterpart. But not all of them. Running client side makes customizing resources hard as well. More on that later.

This will be the essentials of the webpage:

<%@ Page Language=”C#” Inherits=”System.Web.Mvc.ViewPage<dynamic>”%>

<%@ Import Namespace=”System.Net” %>

<%@ Import Namespace=”Telerik.Web.Mvc.UI” %>

 

<!DOCTYPE html>

 

<Html>

    <head runat=”server”>

        <script runat=”server”>

            private void SetAuthCookie(object sender, ResourcesPopulatingEventArgs e)

            {

                HttpCookie cookie = FormsAuthentication.GetAuthCookie(User.Identity.Name, false);

                string cookieHeader = string.Format({0}={1}, cookie.Name, cookie.Value);

                e.Headers.Add(HttpRequestHeader.Cookie, cookieHeader);

            }

        </script>

    </head>

 

    <body>

 

        <% =Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add(“telerik.common.css”))%>

        <form runat=”server” ID=”Form1″>

            <telerik:RadScriptManager runat=”server” EnableScriptGlobalization=”true”>

            </telerik:RadScriptManager>

            <telerik:RadScheduler  ID=”Agenda” runat=”server”

                                   OnResourcesPopulating=”SetAuthCookie”>

                <WebServiceSettings Path=”~/Services/AgendaWebService.asmx” ResourcePopulationMode=”ServerSide” />

            </telerik:RadScheduler>

        </form>

        <%=Html.Telerik().ScriptRegistrar()%>

    </body>

</Html>

The telerik stylesheets are registered, followed by the form containing the scheduler and finished by the Telerik scriptmanager. The webservice is a simple internal asmx, more on that later. Setting the path to the webservice is not enough. On a site requiring authentication, FI by forms authentication, the service will require authentication as well. The authentication cookie is in the session, by default a web service is sessionless. The SetAuthCookie adds the required cookie to the web service request. Setting it is hooked into OnResourcesPopulating, the first event the scheduler will fire.

From webservice to the repository

The web service providing the appointment data is a multi-stage missile. This service should implement a number of methods. These methods return and accept AppointmentData objects. This is a class in the Telerik.Web.UI namespace with properties for the bare essentials of an appointment. In case you want to pass more then that you do so using the Attributes property, which is a complete dictionary.

The webservice methods look like this

[WebMethod]

public IEnumerable<AppointmentData> GetAppointments(SchedulerInfo schedulerInfo)

{

    return Controller.GetAppointments(schedulerInfo);

}

 

A full list of the expected methods is in the Telerik docs.

To interact with your data you need a controller object, the next stage.

private WebServiceAppointmentController Controller

{

    get { return _controller ?? (_controller = new WebServiceAppointmentController(Agenda)); }

}

 

 

The WebServiceAppointmentController lives also in the Telerik.Web.Ui namespace. It’s constructer requires a Provider, which is the third stage.

private AgendaProvider Agenda

{

    get { return _agenda ?? (_agenda = new AgendaProvider()); }

}

 

A provider inherits from SchedulerProviderBase, another class in Telerik.Web.UI. By overriding its members your data is passed to and from the scheduler appointments.

 

public class AgendaProvider : SchedulerProviderBase

{

 

 

    public override IEnumerable<Appointment> GetAppointments(ISchedulerInfo schedulerInfo)

    {

        var repository = DataManager.AfspraakRepository(true);

        var query = repository.Query().Where(a => a.EindTijd >= schedulerInfo.ViewStart).Where(a => a.BeginTijd <= schedulerInfo.ViewEnd);

        return repository.List(query).Select(Appointment).ToList();

    }

 

    private Appointment Appointment(Afspraak afspraak)

    {

        var result = new Appointment

        {

            ID = afspraak.Id,

            Start = afspraak.BeginTijd,

            End = afspraak.EindTijd,

            Subject = Agenda.OnderwerpAsHtml(afspraak),

            Description = afspraak.Notitie,

            RecurrenceRule = “”

        };

        return result;

    }

 

The schedulerInfo passed in contains the information on the selected period. The repository is queried, the private Appointment method creates a Telerik Appointment out of my afspraak (Dutch for appointment) object.

The gotcha here is the Appointment object, also from Telerik.Web.UI, which has loads and loads of interesting members. You can set the properties or try to read their values but passing through the webservice all data will be lost. Just stick to properties also found in the AppointmentData class.

A custom appointment details form

So far the RAD scheduler works nice and well layered. At first sight the three layers in the webservice may look overdone. I guess it is the price for offering other possibilities beside web-service binding ? Anyway, on to adding some of the MVC goodies.

The scheduler has two built in detail forms, a simple in-line and a popup to edit things like the resources of an appointment. Resources are things like available people, rooms and other materials. The scheduler offers quite a lot of possibilities for adding and customizing resources to an appointment. There is also a lot of documentation on customizing the appointment detail form. In the end it was not enough to fit our needs. Our appointments have dynamic resources, for instance the available rooms depend on the assigned worker. There are ways to work with dynamic resources, the downside is that that only works with server-side data binding. We do use the built in resources for some things but ended up using our own form and our own data structures to set the details of an appointment.

Here the MVC controls come into view. There is a lovely modal MVC Window. No problem to add it to the page

 <% Html.Telerik().Window().Name(“AfspraakWindow”)

    .Title(“Details afspraak”)

    .Height(700).Width(1000)

    .Draggable(true)

    .Modal(true)

    .Visible(false)

    .Render();%>

 

The scheduler has lots of client events to hook into, their names are self describing. Popping up the window and filling it with content is done in such a client side event

function OnClientAppointmentSelect(sender, eventArgs) {

    var apt = eventArgs.get_appointment();

    var window = $(‘#AfspraakWindow’).data(‘tWindow’);

    window.ajaxRequest(‘/Agenda/Afspraak/?idAfspraak=’ + apt.get_id());

    window.center().open();

}

 

Again the beauty of the MVC api shows. By issuing an ajax request a controller can provide any view we need.

[NoCache]

public ActionResult Afspraak(int idAfspraak)

{

    return PartialView(new Agenda(Repository.Get(idAfspraak)));

}

 

Data is pulled out of the repository and a partial view is generated. Plain MVC. This view is a complete form with nice Telerik MVC datetime pickers, the Telerik MVC treeview, some serverside script, some javascript, all the usual.

AfspraakDetails

Here it is in action, in the background the scheduler.

Part of the markup, just to demonstrate the availability of the usual MVC stuff

<%if (Model.IsNieuweAfspraak && DataManager.Medewerker.HeeftRol(AdministratieveRol.MaaktPatientAfspraken))

{%>

<tr id=”PatientRow”>

    <td>

        <% =Html.LabelFor(a => a.Patient)%>   

    </td>

    <td>

        <% =Html.DropDownListFor(a => a.Patient,

                                DomainObjectModelBinder<Patient>.SelectListItems(Model.Patienten,

                                                                                    “DisplayNaam”),

                                “– Kies een patient –”,

                                new {onChange = “PatientGekozen();”, style = “width:100%”})%>

    </td>

</tr>

 

The window contains a complete “form”, with a lot of form-data I want to post to my controller. There is a gotcha here. Remember the scheduler living in a form. The window is still part of this same page. Issuing a full post will result in a post to that form. Trying an Ajax form based post also messed up the scheduler. Some script assembly was required to satisfy everybody.

This snippet of (abbreviated) script assembling post data

var laatste = “Laatste= “ + $(‘#Laatste’).val();

var aanvaard = “AanvaardConflicten=” + $(‘#AanvaardConflicten’).attr(‘checked’);

var data = laatste + ‘&’ + aanvaard;

$.post(‘/Agenda/Afspraak/?idAfspraak=<%=Model.Id%>, data, function(result) {

    if (result.Ok) {

        Agenda.rebind();

        CloseWindow();

    }});

 

Here the value of only two controls is used, just expand the string for any others. The assembled data is posted to my controller by issuing a Jquery post.. To the controller the data looks like any other usual form data.

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Afspraak(int idAfspraak, FormCollection form)

{

 

    var model = new AfspraakModel(idAfspraak, form["Laatste"]);

 

    var persist = model.Persist();

    return Json(new { Ok = persist });

}

 

The posted data is read from the form collection. Here (again abbreviated) I extract it by hand, it could also be used with (Try)UpdateModel. The controller returns some Json to notify the window of validation and persistence results. Making the circle round.

Winding down

The voyage through Telerik country has been an interesting one. Despite the somewhat frightening, almost old-fashioned, radical name the scheduler works well with all today’s tools. Most of the information on how to do that can be found on the Telerik web site. Also mentioned should be Telerik support. When it comes to to simple questions the response can be almost instantaneous. When it comes to deeper problems the response can take longer but does provide an answer. Which can be in the form of a complete web-cast to guide you through something. Hats off.

Telerik does also spend a lot of effort in marketing. Having spent a lot of time on their site I can no longer watch  the Carter Family (Kyle is not the only hillbilly on CB Smile) on YouTube without a Telerik ad popping up. That’s too much, even from a good friend.

Posted in Uncategorized | 7 Comments

Models for a view (some objects are more equal than others)

How to implement the V and the C in MVC is no point of great discussion. When it comes to the M the variation increases. An ASP.NET MVC app has a Models folder; what you will find in there varies among the many samples found. The folder looks a bit like a dumping place for the author’s favorite technology, be it EF, sql data adapters, web-services, domain objects, pure agnostic view models or whatever else comes into imagination.

In this post I will explore a little bit what kind of models to use. In case you consider the only just solution a pure view model, as presented in MVVM (model View ViewModel), you do have a valid best practice. Read on nevertheless for reasons why that’s good. Models based explicitly on an technology like ado.net are a bad practice, that is beyond discussion. Left in the middle are things like domain-objects. Mapped (FI) by nHibernate to a sql database and served to your app through repositories. To your app these objects are plain objects (POCO’s), at first sight not hindered by any underlying technology. In a real app they do have some behavior, lazy loading being only one aspect of that, which might fire back.

Can you use such a mapped domain object in a View ? As said, the best practice is to wrap up the object in a ViewModel. With a different model for every view. In real life not everybody does that. It can be tedious and a maintenance nightmare. In quite a number of cases we do use domain objects in our views. Which does work provided you treat them with care.

When presenting data lazy loading sticks up it’s head. It will fire when the view is actually rendered. Which happens after the controller action has completed. As long as the session to the database is still available that will work. I spent my last post on that.

When updating a domain object from posted data real danger emerges. I’ve seen very poisonous recipes (pun again intended) doing that. They boil down to the following snippet. There is a DO Patient, in the view a patient’s data has been edited and is now posted back to the controller to be persisted to the database.

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Patient(Patient patient)

{

    Repository.Persist(patient);

    return PartialView(patient);

}

What will happen is that the MVC routing will find a match for the controller action. It will create a new patient object and populate that with the form’s data. Also when the data belonged to a existing patient. The original sample contained some fiddling to try to restore that. But that should not be the way, deep down below you are messing with nHibernates’s deep inner workings. Something you would rather stay on good terms with.

There is a neat way out. Change your action to the following

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Patient(int patientId, FormCollection form)

{

    var patient = patientId == 0 ? Repository.New() : Repository.Get(patientId);

    TryUpdateModel(patient);

    Repository.Persist(patient);

    return PartialView();

}

The controller is now “aware” of an identifying Id of the DO. Which is going to be part of the route parameters of the form

using (Ajax.BeginForm(“Patient”, “Patient”, new { patientId = Model.Id }, new AjaxOptions { UpdateTargetId = “patientnaw” }))

        {

When posting back the routing will hit our action. Which now has the Id to get the (new) patient’s data from the repository. TryUpdateModel then updates the patient from the posted back formdata in the second parameter, after which the patient can be persisted. In your real app you should of course check the result of TryUpdateModel and do some real validation. For now that is beyond the scope of this post.

What should be clear is that it is a one way street, the DO’s can flow from controller to the view, but don’t ever expect the view to post back a real DO. Whether to work with only pure, really agnostic, ViewModels or nevertheless to use DO’s straight from the repository is up to you. I hope to have shown you some of the pitfalls, and a way out, of doing the latter.

Posted in Uncategorized | 6 Comments

(Yet another) nHibernate sessionmanager for ASP.NET (MVC)

Working with a nHibernate session in an asp.net web application is a subject to many a blog post, forum question or overflowing stack. Having already made a contibution before, I am nevertheless going to add another go at it combining all I’ve met and trying to find a way to meet the objections to the different approaches.

The problem

Accessing a database via nHibernate takes four steps.

  1. Create a sessionfactory. 
  2. Open a session.
  3. Access data
  4. Close the session

Creating a sessionfactory is a very costly process, don’t do this to often. Opening an ADO connection results in an open connection to the database. Database connections are a costly external resource. Despite session pooling connections should be closed as soon as possible. An nHibernate session wraps up the ADO connection; it handles the opening and closing. Creating an nHibernate session is fast and will not be costly until the moment the ADO connection is opened. Nevertheless this is not a license to spill.

Strategies

Trying to balance to cost of creating a sessionfactory and the waste of creating sessions which will not be used I’ve found several ways to manage the session.

  1. Do it yourself.  Create the factory whenever the app needs data and fiddle on from there optimized to the occasion. Needless to say that’s not going to work unless you have a very simple app.
  2. An action in a (MVC) controller. Using an attribute on the action a factory and session are created on the start of an action and disposed when the action is finished. This might look appealing but is a very poisonous recipe (pun intended). After the action is finished the page will be rendered. In case there are any lazy properties on the page they cannot be read because the session has already closed.
  3. The Web-HttP request. At the start of the request the session is opened, at the end it closed. This is by far the favored solution by almost everybody. The down side is that, in the default implementation, a session is created on every request. Also when no database access will take place, even when requesting an image or the like.

Objectives

The session manager presented here is controlled by web requests and has some extra’s

  • Only create a factory and  session when one is actually needed.
  • Can also be used in a non web environment. Like Visual studio to run in an unit test.

The first extra is done by making the session a lazy property. The second one by setting the NH-session context based on the app’s context.

The (a)  solution

So far for the theory, here’s the code. It’s using fluent nHibernate for setting the configuration. What else ?

public class SessionManager

{

    private static ISessionFactory Factory { get; set; }

    public static string ConnectionString { get; set; }

 

    static SessionManager()

    {

        ConnectionString = @”Data Source=Bunocephalus;Initial Catalog=Epos4;Integrated Security=true”;

 

    }

 

    private static ISessionFactory GetFactory<T>() where T : ICurrentSessionContext

    {

        return Fluently.Configure().

            Database(MsSqlConfiguration.MsSql2008.

 

#if DEBUG

                            ShowSql().

#endif

                            ConnectionString(c => c.Is(ConnectionString))).

            Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())).

             CurrentSessionContext<T>().

            BuildSessionFactory();

    }

 

 

    public static ISession CurrentSession

    {

        get

        {

            if (Factory == null)

                Factory = HttpContext.Current != null

                                ? GetFactory<WebSessionContext>()

                                : GetFactory<ThreadStaticSessionContext>();

            if (CurrentSessionContext.HasBind(Factory))

                return Factory.GetCurrentSession();

            ISession session = Factory.OpenSession();

            CurrentSessionContext.Bind(session);

            return session;

        }

    }

 

    public static void CloseSession()

    {

        if (Factory == null)

            return;

        if (CurrentSessionContext.HasBind(Factory))

        {

            ISession session = CurrentSessionContext.Unbind(Factory);

            session.Close();

        }

    }

 

    public static void CommitSession(ISession session)

    {

        try

        {

            session.Transaction.Commit();

        }

        catch (Exception)

        {

            session.Transaction.Rollback();

            throw;

        }

    }

}

 

A short walkthrough:

The public property CurrentSession is the only thing your other code is interested in. It will be used in your repositories.

public virtual T Get(int id)

{

    var session = SessionManager.CurrentSession;

    var domainObject = session.Get<T>(id);

    return domainObject;

}

 

Which should speak for itself

The factory is a private member. CurrentSession checks if the factory is already created. When not it passes a type parameter, which depends on the context, to the GetFactory method which actually instantiates the factory. In case the manager is running in a web context the factory is given a WebSessionContext else a ThreadStaticContext. The latter working well when running a test. A sql2008 database is assumed with the table mappings in the same assembly. I leave it up to you to make this configurable. In case you really need it Smile

The actual session is managed by nHibernate itself in the sessioncontext.  CurrentSession checks that to try to get the session. When none is available it creates one and binds it to the context. Now all code in one webrequest will share one and the same session.

When closing the session the code should check for a factory. Perhaps the current webrequest never did any database access and thus never opened a session. Close session unbinds the session from the context and closes it.

In several solutions, including the one in the original version of this post, the sessionmanager handles (part of) transaction management. The most extreme version starts a transaction when opening the session and commits that when closing the session. Which could look nice at first sight. But it will fire back at you. We have several developers working on this project, not everybody that familiar with nHibernate. The things nHibernate (tries to) persist implicitly can be quite surprising, resulting in baffled co-workers. Making persisting object explicit in transactions is also good from an organizational point of view. Which  strategy to follow is beyond the scope of this post. The CommitSession helper method handles the core of that.

Some checks in this code might seem superfluous. But this way it does survive some very nasty crashes doing heavy ajax stuff in VS always clearing all database connections. The last thing you need there is a conflict with your sql server.

Note this part in configuring the factory

#if DEBUG

ShowSql().

#endif

This results in all nHibernate generated sql to show up in your test.

NHunit

The full picture

The database part of the solution has two projects. One are the repositories, the other one is this nHibernatemanager. Which contains

  • The sessionmanager we discussed
  • An HttpModule to load the manager in a website
  • The mappings of the domain model
  • A validator, not discussed here

Solution

The HttpModule to wrap up the manager:

public class CurrentSessionWebModule : IHttpModule

{

    public void Init(HttpApplication context)

    {

        SessionManager.ConnectionString = ConfigurationManager.ConnectionStrings["EposDB"].ConnectionString;

        context.EndRequest += (sender, e) => SessionManager.CloseSession();

    }

 

    public void Dispose()

    {

 

    }

}

Closing the session is hooked into EndRequest. In the “usual” solution opening the session is hooked into the BeginRequest. Here this is not needed, the session will be opened on demand by any code actually needing a session.

Loading is configured in web.config.

<httpModules>

    <add name =CurrentSessionWebModule type=Epos4.Database.NhibernateManager.CurrentSessionWebModule, NhibernateSessionManager, Version=1.0.0.0, Culture=neutral/> 

</httpModules>

 

This is the only mentioning of the manager needed by the website. To get to data it uses the repositories, the repositories reference the actual code of the manager.

That’s it. We have pushed the management of a session away into one specific corner, have a session at our disposal when needed and are not hindered by a performance or resource penalty when not needing a session. Nothing original, just works like a charm. And any remarks or suggestions are more than welcome.

<update>Your comments have been used to update this post where it was plain wrong. The original version assumed an nHibernate session always opens a connection to the database. It does not. Thank you for your feedback</update>

Posted in ASP.NET, Data | 20 Comments

Book review: Learning Monotouch by Michael Bluestein

Monotouch is a powerful tool to create native iOS (iPhone/iPad/iPod) apps written in C# backed by (a native version of) the .net framework. I have been using it for some time now to my great satisfaction. Learning Monotouch was a somewhat bumpy road. The native language for iOS is objective C and the majority of the resources on iOS development use that language. Objective C is on itself not a bad language at all. But the syntax is somewhat awkward and the philosophy differs enough from C# to make the learning curve for us .net-ers rather steep.

There are a lot of resources on the web on Monotouch, a lot with practical hands on examples. They do learn you how to build working (and appstore accepted apps) but not many of them spend any attention on the background or architecture of iOS. Making it hard to understand all Objective C resources, even having learned the syntax.

Learning Monotouch “A hand-On Guide to Building iOS Applications with C# and .NET”, by Michael Bluestein ,  is the book I wish I had had when I started working with Monotouch.

LM

The book is a hands-on guide, everything is explained in clear example apps. In the first chapters the same app is demonstrated in XCODE-Objective C (Apple’s tools)and in Monotouch. Doing so it both explains the architecture of an iOS app and explains the way Monotouch handles that. In case you are already working with Monotouch: do get this book and do not skip these first chapters. Besides a better understanding of your apps Michael also spends a lot of attention to the details, there is a lot of quality to be won in fine tuning the result of the default app template.

The book assumes you are familiar with C#, lambda expressions and extension functions are used without introduction. Those things show how good an idea Monotouch is, these are powerful language features not offered by objective C. The book also assumes you are familiar with the .Net framework. Parts are used throughout the chapters. “Our” framework really has more to offer than the native Apple tools, especially when it comes to webservice clients and xml.

The components which make up iOS, visual and non visual, are wrapped up by Monotouch in C# classes. In a number of chapters all pass the revue, ranging from views to the music player. Tables and navigation get a chapter of their own, they are the backbone of almost any iOS app. Thank goodness Michael does start a navigation app with the default windowed app template. Xcode (and thus Monotouch) has a template for a navigation based app, my experience with that is not that good. The way Michael treats navigation in an app works completely outshines all I have ever found so far on the subject. Working through it results in an app that is easy to understand, well integrated and is guarded against common problems. Like popping to a view which has unintended been garbage collected in the mean time. Leading to a blank screen, many an app (including mine..) can suffer from this behavior. Having worked through this chapter I now know how to (really) solve this.

Monotouch and Michael’s coverage don’ stop with of-the shelf components. You can also do hard core bare graphics and animations yourself, the chapter “Graphics and Animations” provide a good start for that. Locations (using GPS) and a chapter on Google Maps using the MapKit follow. Again all very clear and complete containing the essential secrets like how to keep recording location data when your apps switches to the background. Again, this is the book I should have had when I started Smile

A whole chapter is spent on connecting to webservices. SOAP style as well as REST style. Here the .net framework shines again. Networking has a chapter of its own. Which treats the iOS GameKit, which turns out to be a complete peer to peer networking API, and Bonjour, Apple’s networking infrastructure API. In a demo app a client-server scenario, using two iOS devices (!). is demonstrated.

Storage has a chapter of its own. Which describe how to work with app settings (like app.config in .net) and SQLite. SQLlite is not a part of iOS itself, it’s a third party open source database. Using that, will give your app ADO.NET style database access. The nice thing is that several apps can share one and the same database file, a good way to reach out of your app’s sandbox.

A final chapter is spent on the iPad. Having a larger screen it offers specific  components to fully utilize that. Michael covers these components and explains how to make your app device aware, with specific screens for iPhone and for iPad.

The book is not about cross-platform development. Monotouch is not a tool for a straightforward port of a Windows phone or MonoDroid (C# for Android) app. Such a tool does not exist, simply because these platforms are different. They are different in the way an user works with apps, they are different in how the user expects the apps to behave. Windows Phone has the Metro interface, which works different as navigating through tables as an iPhone user is used to. You cannot port that, you have to rethink your UI. What can be ported is the non-visual part of the app, where the business logic should be. These parts can be ported, Michael does spend some writing on that, though not that much. Needless to say a good architecture pays of and is beyond the scope of this book.

Some words on the style of the book. It is a hands-on book where your teacher is talking to you, using words like “Let’s create an app” and recipe style fragments. This is a way of writing I do appreciate being “guilty” of doing it myself too. But feedback I received, both from readers and editors, indicates that not everybody does favor it.

To conclude: I can only be lyrical about this book. Once more: I wish I had read it last year. In case you do anything with iOS and .net, just get it. In case you don’t do anything with iOS yet, get it too and expend your C#/.net skills. I hope my walkthrough  of the book, and thus of the platform has hinted at the richness of iOS. Let Michael enlighten you to bring it more great apps.

Posted in Mobile, Uncategorized | 7 Comments