Telerik blogs

<-- Read Part 1

Now that we have the visual portion of the application built, we need to start to wire it up to a database. When you build applications of your own, you will probably already have a backing database that you want to connect to.

Connecting To SQL Server From A Mobile Application

You may be familiar with connecting directly to SQL Server using ADO.NET and a SQL Connection defined in your configuration file. What happens when you do that? Under the covers, .NET establishes a connection to SQL Server using the native SQL Server driver over TCP/IP. Usually you return data into some sort of container (DataSet, LINQ Context or EF Entity Model), and then you connect some sort of visual component (like a grid) to the container and select which fields to display.

This is a very proprietary connection. Since our little mobile app is not running on .NET, it can't make this kind of a direct connection to SQL Server. So how do we get data from the database into this application?

The answer is a Web Service. Web Services have a rather obscure meaning. Sometimes we think about a service in terms of which technology is used to built it (WCF), or the protocol it implements (SOAP). However, a web service is simply data returned from a URL. Instead of returning a page, you return data that is serialized in some form (either XML or JSON). SOAP is probably the most famous XML based web service protocols. It's also typically the most straightforward to use with .NET since it automatically gets proxied to a .NET object, meaning you get an instance of a class and don't have to worry about serializing the yucky XML underneath.

SOAP Is Dirty. JSON Is FUN!

The problem with SOAP or XMl is that it's terribly difficult to read if you aren't a computer. Also, it's extremely verbose and every byte counts over our flaky mobile connections. Furthermore, since our little app is not using .NET, we don't want to be tasked with manually reading and parsing a SOAP web service. Instead, we can expose the data as JSON (JavaScript Object Notation) which is easy to both read and parse. We can do this using any variety of ASP.NET Technologies. The easiest way to build a simple JSON service is to use an ASP.NET MVC project.

Create The Service Layer

Add a new project to the solution called the-facts.data. Use the MVC 4 (or 3), project template and choose the empty template.

Once the project loads, you may go ahead and delete the Views folder. This project will not be providing any UI, only the data that we need for our hybrid mobile application.

At this point, I am going to be using a SQL Express database that you can download and attach to your own project. It has 3 tables in it...

  1. Joke
  2. Category
  3. JokeCategory

There are 3 categories of Jokes, and jokes are matched with categories via the JokeCategories table.

To get the data out of the database, I am going to be using Entity Framework.

Retrieving Data

Add a new ADO.NET Entity Data Model called "ChuckNorrisModel". Select the "SQL Server Database File" adapter, and browser to the location where you downloaded the ChuckNorris.mdf database file. This should then open the "Entity Data Model Wizard".

When you select "Next" on the first screen (just take the defaults), you will be asked if you want to copy the database file into your project. You should select "Yes". Now you will be asked which tables to select out of the database. Select the Category, Joke and JokeCategory tables. Click Finish.

The EF Designer will open and you will only see two of the three tables that you selected. That's because the JokeCategory table is reflected in the form of a relationship, not a physical table since that is in fact what it is. Isn't EF smart?!

Now it's time for us to expose this data via a Web Service. To do that, create a new Empty WebAPI Controller in the Controllers folder. Call it JokesController.

We can add a Get method to this controller that will automatically be called when a user visits the /api/jokes endpoint. For now, just return a string saying "Hello World".

Simple JokesController Get Method

public class JokesController : ApiController
{
    public string Get() {
        return "Hello World";
    }
}

You can now visit the /api/jokes url in your browser. Depending on which browser you use, you will see different results. IE will ask you if you want to download the "jokes.json" file. Chrome will display it as XML.


Congratulations! You have just built a JSON web service. It doesn't return any actually useful data though, so let's change the Get method on the JokesController to return us some Chuck Norris facts instead.

Returning Database Data Via JSON

Before we can begin returning data, we need to setup our project for success with a good structural pattern. One that you will frequently see in .NET projects is a pattern call the "Repository Pattern". The idea in the Repository Pattern is that you have a Repository class that interacts with the database, and the controller method simply calls the repository class and returns that result. This decouples your database logic (gets, updates, deletes and so on) from the controller, which is primarily responsible for returning the visible portion of the application. In our case, we are only building an API, but it's still a good practice to follow since (generally speaking), the more decoupled we can make our application, the easier it is to test and maintain.

Create a folder in your project called "JokesRepository". Within that folder, create a new class called JokesRepository. The "JokesRepository" class should define a generic Get method that returns a list of all the jokes.

public class JokesRepository {

    readonly Data.ChuckNorrisEntities _entities = new Data.ChuckNorrisEntities();

    public IQueryable<Models.Joke> Get() {

        return _entities.Jokes.Select(j => new Models.Joke {
            JokeId = j.JokeId,
            JokeText = j.JokeText,
            Category = j.Categories.Select(c => new Models.Category {
                CategoryId = c.CategoryId,
                Description = c.Description
            }).FirstOrDefault()
        });

    }
}

You may notice from that previous snippet that I'm selecting out of entity framework and into Models.Joke/Models.Category classes. This is because the Entity Framework objects that represent these tables contain FAR too much information, and are difficult if not impossible for .NET to turn into JSON. This means that we can't return them from the "JokesController". To get around this, we create simple models that reflect the structure of the tables with properties, and then map the EF objects into these simple classes which can be returned from WebAPI controllers.

Create a folder called Models, and then add Joke.cs and Category.cs classes.

Category Model

public class Category {
  public int CategoryId { get; set; }
  public string Description { get; set; }
}

Joke Model

public class Joke {
  public int JokeId { get; set; }
  public string JokeText { get; set; }
  public Models.Category Category { get; set; }
}

For our application, we only want one random joke displayed at a time. For this to work, we need to randomly select a joke from the database based on the "clean" or "explicit" category. I had to do a little research to figure out how to execute a query to get a random result with LINQ, but it turns out that it's quite easy.

Full JokeRepository Code

public class JokesRepository {

  readonly Data.ChuckNorrisEntities _entities = new Data.ChuckNorrisEntities();

  public Models.Joke Random(string jokeType) {
    var jokes = Get();
    return jokes.Where(c => c.Category.Description == jokeType)
        .OrderBy(x => Guid.NewGuid())
        .Take(1).FirstOrDefault();
  }

  public IQueryable<Models.Joke> Get() {

    return _entities.Jokes.Select(j => new Models.Joke {
        JokeId = j.JokeId,
        JokeText = j.JokeText,
        Category = j.Categories.Select(c => new Models.Category {
            CategoryId = c.CategoryId,
            Description = c.Description
        }).FirstOrDefault()
    });

  }
}

We now have the backing data access to return this data via the JokesController. Since we are allowing users to select a joke by category via our API, we just ask for that as a parameter and send it through to the Random method on the "JokesRepository" class. If the user asks for jokes in a category that don't exist, they will simply get an empty results set. No harm no fowl.

JokesController Returns Random Joke By Category

public class JokesController : ApiController
{
  readonly Repositories.JokesRepository _jokes = new Repositories.JokesRepository();

  public Models.Joke Get(string type) {

    return _jokes.Random(type);

  }
}

If you were to visit the /api/jokes url, you can add in a category URL parameter to return an "explicit" or "clean" joke.

Now we are ready to tie in this simple web service to our mobile application. We would normally publish our API to a web server (probably IIS), but for now, you can just use your development server URL. It works just fine too! 

For your convenience, we have published this WebAPI project to Azure so you can use it yourself without having to setup the service layer.  It's located at http://facts.azurewebsites.net/api/.

Accessing Services From Icenium Apps

Since Icenium applications are at their core just web applications, we can use AJAX to call our new web service. Since the application we are building uses Kendo UI Mobile, that means that it already includes jQuery. And since we have jQuery, making AJAX calls is incredibly easy.

In order to begin adding this business logic into our mobile application, we're going to use JavaScript. If you aren't well versed in the eccentricity of the language, or you plain just don't feel comfortable with JavaScript, don't worry. JavaScript can feel like a tough transition to make from C# or VB. In reality though, it's a very tolerant and forgiving language. This makes it very easy to use when you know how to structure it and debug it. This is why it's become so popular in the last few years!

Let's walk through creating a new JavaScript file that we can use to add the needed code to our mobile app.

Create a new file in the Icenium the-facts project called app.js and place it under the scripts folder. Before we start writing JavaScript, we need to set ourselves up for success. We're going to do that by putting all of our code inside of a function that executes itself. This is one of the goofy conventions that you will see a lot of in JavaScript. The reason that we do this is that JavaScript has to have a place to put any variables or objects we create. By default, it puts all of these items on the window object. This is the top level JavaScript object that exists on every page. By placing all of our code inside a function that executes itself, we protect the window object from being polluted by our custom objects.

app.js Wrapper Function

(function() {

  // all of our application code will go here

}());

Now lets think about what needs to happen. When the application loads, it needs to retrieve a random joke from the database. First, lets create the function that will call our service and retrieve the random joke.

Retrieve A Random Joke Using AJAX

(function() {
  // using the development server url here
  var api = "http://localhost:5421/api/";

  var getRandomJoke = function() {
    $.get(api + "jokes?type=nerdy", function(data) {
      // the data object contains the joke
    });
  };

}());

At this point, we have the function to return the data from our web service, but there are two big questions here.

  1. How do I call this function from the HTML?
  2. How do I get the joke text into the HTML?

In order to solve both of these issues, we're going to encapsulate this function inside another object that we safely attach to the window object. This is another common practice for JavaScript.

Encapsulate the Joke Logic And Attach To The Window

(function() {
  // using the development server url here
  var api = "http://localhost:5421/api/";

  // create a variable on the window to hold all of our custom code
  window.app = {};

  // create a nerdyModel to encapsulate all of the logic needed for the nerdy jokes view
  window.app.nerdy = (function() {

    var getRandomJoke = function() {
      $.get(api + "jokes?type=nerdy", function(data) {
        // the data object contains the joke
      });
    };

    // anything that is returned out of this function will be available
    // on window.app.nerdy
    return {
      getRandomJoke: getRandomJoke
    }

  }());

}());

The second issue we could solve one of two ways. We could select the <h3> inside of the Nerdy view with jQuery and update it's text, but it's easier to let Kendo UI do that for you. The way that we accomplish this is by creating a something called a ViewModel.

A Quick Word On The MVVM Pattern

ViewModels is a term derived from the pattern Model View View-Model(MVVM). This was a pattern or technique devised by Microsoft in the early days of XAML. It was later ported to JavaScript via the KnockoutJS library. Kendo UI has it's own implementation of MVVM. The idea is that instead of having to have data in our JavaScript code and in the HTML, and having to manually keep them in sync, you instead only worry about your data in your JavaScript code. Kendo UI will worry about making sure the change is reflected in the HTML.

To get this setup, we need to create a Kendo UI Observable which will act as our view model. Once we have that object, we can use special data-bind syntax to glue this JavaScript object and it's values to our HTML. In the case of the nerdy model, we just need a joke property that will hold the text of the current joke. Anytime we read or update the view model, we do so using a special get and set method. These methods tell Kendo UI "Hey! I just read or changed the ViewModel." Then Kendo UI runs off to make sure that all of the HTML that is bound to the view model gets changed too, so everything is always in sync.

Full Nerdy View Code With View Model

(function() {
  // using the development server url here
  var api = "http://localhost:5421/api/";

  // create a variable on the window to hold all of our custom code
  window.app = {};

  // create a nerdyModel to encapsulate all of the logic needed for the nerdy jokes view
  window.app.nerdy = (function() {

    var getRandomJoke = function() {
      $.get(api + "jokes?type=nerdy", function(data) {
        // update the view model
        viewModel.set("joke", data.JokeText);
      });
    };

    // create a view model which we can bind to the HTML
    var viewModel = kendo.observable({
      joke: null
    });

    // anything that is returned out of this function will be avaialble
    // on window.app.nerdy
    return {
      getRandomJoke: getRandomJoke,
      viewModel: viewModel
    }

  }());

}());

Now we're ready to wire up the HTML to our JavaScript.

Calling JavaScript From Kendo UI Mobile Views

First, declare the model for the view by using the data-model property for the Kendo UI Mobile View. Then bind the HTML of the <h3> to the joke property. Since we already declared the model for the view, we can reference the joke field directly.

Define The Model For The View

<!-- the nerdy jokes -->
<div data-role="view" id="nerdy" data-layout="main" data-model="app.nerdy.viewModel" data-title="The Facts: Nerdy">
    <h3 data-bind="html: joke"></h3>
</div>

We want to pre-populate this view with a joke. To do this, we are going to use the init method of the view by specifying data-init. This is the function that will be called when the view is loaded. Lastly, we also need to move our mobile application initialization code out of the index.html page and into the very bottom of the app.js file.

Full HTML Code

<!DOCTYPE html>
<html>
<head>
    <title>Kendo UI DataViz</title>
    <meta charset="UTF-8" />

    <link href="kendo/styles/kendo.dataviz.mobile.min.css" rel="stylesheet" />

    <!--Once the final theme is chosen the redundant css reference should removed-->
    <link href="kendo/styles/kendo.dataviz.flat.min.css" rel="stylesheet" />
    <link href="kendo/styles/kendo.dataviz.silver.min.css" rel="stylesheet" />

    <link href="styles/main.css" rel="stylesheet" />

    <script src="cordova.js"></script>
    <script src="kendo/js/jquery.min.js"></script>
    <script src="kendo/js/kendo.dataviz.mobile.min.js"></script>

</head>

<body>

    <!-- the nerdy jokes -->
    <div data-role="view" id="nerdy" data-layout="main" data-model="app.nerdy.viewModel" data-title="The Facts: Nerdy" data-init="app.nerdy.getRandomJoke">
        <h3 data-bind="html: joke"></h3>
    </div>

    <!-- the nerdy jokes -->
    <div data-role="view" id="explicit" data-layout="main" data-title="The Facts: Explicit">
        <p>Explicit Chuck Norris facts will go here.</p>
    </div>

    <!-- the nerdy jokes -->
    <div data-role="view" id="dashboard" data-layout="main" data-title="Dashboard">
        <p>Chuck Norris charts will go here.</p>
    </div>

    <!-- the common layout for all views -->
    <div data-role="layout" data-id="main">
        <!-- the footer widget pins content to the top of the screen -->
        <div data-role="header">
            <!-- the navbar widget creates a title bar which can also hold buttons -->
            <div data-role="navbar">
                <!-- the view-title widget displays the value of whatever is in the 'data-title' attribute on the current view -->
                <span data-role="view-title"></span>
            </div>
        </div>
        <!-- the footer widget pins the content to the bottom of the screen -->
        <div data-role="footer">
            <!-- the tabstrip widget creates the familiar mobile tabstrip -->
            <div data-role="tabstrip">
                <!-- each tabstrip button is an anchor. It's href attribute points
                     to the id of the view that should be shown when that items is tapped. -->
                <a href="nerdy" data-icon="home">Clean</a>
                <a href="explicit" data-icon="delete">Explicit</a>
                <a href="dashboard" data-icon="more">Dashboard</a>
            </div>
        </div>
    </div>

    <script src="scripts/app.js"></script>

</body>
</html>

Notice that I've added a script tag for the app.js as the last line in the <body> At this point, your JavaScript should look like this:

Full JavaScript Code

(function () {
    // using the development server url here
    var api = "http://localhost:5421/api/";

    // create a variable on the window to hold all of our custom code
    window.app = {};

    // create a nerdyModel to encapsulate all of the logic needed for the nerdy jokes view
    window.app.nerdy = (function () {

        var getRandomJoke = function () {
            $.get(api + "jokes?type=nerdy", function (data) {
                // update the view model
                viewModel.set("joke", data.JokeText);
            });
        };

        // create a view model which we can bind to the HTML
        var viewModel = kendo.observable({
            joke: null
        });

        // anything that is returned out of this function will be avaialble
        // on window.app.nerdy
        return {
            getRandomJoke: getRandomJoke,
            viewModel: viewModel
        }

    }());

    // create a new kendo ui mobile app using the whole page
    new kendo.mobile.Application(document.body, { transition: "slide" });

}());

How Far We've Come

If you run the application now, it will load up and you will see a nerdy Chuck Norris fact. Excellent! Let's add a button to the top Navbar so that the user can request a new Chuck Norris fact whenever they want.

Overriding Layouts

Our button for requesting a new random fact will go in the Navbar. If you remember, our Navbar is in the layout that all the views are using. In order to not have the button show up on every view, we are going to override the Navbar portion of the layout in the nerdy facts view. Whenever a view has a layout defined in the data-layout element, but also has portions of that layout defined within the view, the view layout wins.

We can add a button to the Navbar with a refresh icon and align it to the right.

Add A Refresh Button To The Navbar

<!-- the nerdy jokes -->
<div data-role="view" id="nerdy" data-layout="main" data-model="app.nerdy.viewModel" 
  data-title="The Facts: Nerdy" data-init="app.nerdy.getRandomJoke">
  <!-- this header overrides the header defined in the layout -->
  <div data-role="header">
    <div data-role="navbar">
      <span data-role="view-title"></span>
      <button data-role="button" data-align="right" data-icon="refresh" data-bind="click: refresh"></button>
    </div>
  </div>
  <h3 data-bind="html: joke"></h3>
</div>

You can see how I used a simple <button> element to create the button in the Navbar. Then I used the data-align attribute to push it to the right-hand side. The data-role attribute tells Kendo UI Mobile to style this button appropriately, and the data-icon attribute to add a refresh icon to the button. You can check our documentation for a list of all of the icons you can use with Kendo UI Mobile.

I also bound it's click event to a refresh event in the ViewModel. This refresh event simply calls the "getRandomJoke" method which then sets the joke value of the ViewModel, and the joke text changes.

Add Click Event To ViewModel

// create a view model which we can bind to the HTML
var viewModel = kendo.observable({
    joke: null,
    refresh: function() {
      getRandomJoke();
    }
});

Now running the app will give you a default random joke, and the refresh button updates the view with a new joke.


You're now ready to proceed to part 3, where we change the icons and skin of our mobile application, use some native device features, and then top it all off by actually building this Icenium project into a mobile application. Before you proceed, make sure you grab your fully functional 30 day free trial of Icenium.


Burke Holland is the Director of Developer Relations at Telerik
About the Author

Burke Holland

Burke Holland is a web developer living in Nashville, TN and was the Director of Developer Relations at Progress. He enjoys working with and meeting developers who are building mobile apps with jQuery / HTML5 and loves to hack on social API's. Burke worked for Progress as a Developer Advocate focusing on Kendo UI.

Related Posts

Comments

Comments are disabled in preview mode.