Building a high score web service for a WP7 Game (Part I)

by Niels Derdaele 11. April 2011 22:44

Download source files – 161 kB

A friend of mine has been asking me how he could create an web service which stores achievements that users obtained in an WP7 game. I decided to write a little post about this. In this post I’ll keep it rather simple and explain how you can create a web service that stores high scores from a user (and of course how to consume it from within a WP7 game).

Creating a WCF Service Application

To create our web service we’ll use the Windows Communication Framework (WCF), for those of you who never heard of WCF, it’s an application programming interface (API) in the .NET Framework which allow us to build connected, service-oriented applications.

1. Let’s begin by creating a new project, choose for a WCF Service Application under WCF.

New Project

2. You might notice that Visual Studio has created an example service for us, however we don’t need it and we can safely delete the files IService1.cs and Service 1.svc.

image

3. Now that we’ve deleted these files we will add an WCF Service, let’s call it HighScoreService.svc

image

4. You’ll notice that Visual Studio has added three new files (HighScoreService.svc, HighScoreService.svc.cs and IHighScoreService.cs). We can access HighScoreService.svc.cs either by using the arrow in front of HighScoreService.svc or by simply double-clicking on HighScoreService.svc. The only two files we’ll need in this example (and in most situations) are IHighScoreService.cs and HighScoreService.svc.cs.

Submitting a high score

Visual Studio has provided us with a template, just edit the function you’ll find in there to an SubmitHighScore function as shown below

namespace NielsDerdaele.HighScoreSample.WCF {    
    [ServiceContract]
    public interface IHighScoreService {
        [OperationContract]
        void SubmitHighScore(string uniqueId, int score);
    }
}

You might notice that SubmitHighScore has an attribute in front of it [OperationContract], functions with this attribute are accessible through our web service, this implies that we can still force every service that implements IHighScoreService to have a specific functions without having to make it accessible through the service, we could do this by dropping the [OperationContract] attribute.

Now that we’ve created our contract, we have to implement it. To do this: go to HighScoreService.svc.cs and use the built-in feature to implement an interface as shown below.

image

While you’re at it, also remove DoWork() as we don’t need this anymore. Now that we’ve implemented this interface we want to save our high score to a database. So let’s begin by adding a new database to our project.

Creating a database through Visual Studio 2010

Right-click on App_Data and choose for Add -> New Item. Choose for a SQL Server Database under Data

image

image

This will add an empty database file in our App_Data folder, off course we want to add a table and some columns to this database, to do so just double click on HighScoreSampleDatabase.mdf, this should open up your Server Explorer. Before adding tables, make sure you are working in the correct database in case you have multiple data connections!

Right-click on Tables and choose Add New Table.

image

Make two columns (UniqueId – varchar and Score – int) as listed below, make sure Allow Nulls is unchecked.

image

Now let’s make an surrogate key by adding another column called Id (int), then right clicking on it and pick Set Primary Key (or use the button in the toolbar) and finally set Identity Specification to Yes in the Column Properties.

image   image

Don’t forget to save(ctrl+s) the table before continuing!

image

As stated before this is a simple web service and because of this I decided to keep the database also very basic, in a real life application you probably want to separate the users and their scores (which would probably contain a lot more information then just an integer value). Furthermore the UniqueId could then perfectly be used as a Primary Key (we can’t do this now as this would limit the possibility of adding multiple scores coming from the same user).

Connecting to our database using the Entity Framework

Now that we’ve created the necessary table and columns in our database, we’ll add an ADO.NET Entity Data Model. This is a model based on the Entity Framework which is an object-relational mapping framework in .NET

Right-click on your project and choose Add –> New Item, this time pick ADO.NET Entity Data Model

image

You should see a wizard popup that will help you to create your model, begin by choosing Generate from database

image

Make sure you pick the correct connection in case you have multiple connections in the dropdown box

image

Select the table we create before and make sure you select “Pluralize or singularize generated object names”

image

After clicking Finish a new file called HighScoreSampleModel.edmx should be added to the project and Visual Studio will open this file, we can just close it (Tip: if you edited your database you can regenerate the model by right-clicking in the designer of this file and choosing Update Model from Database).

Alright! We’ve added a database and made it accessible through an ORM, now let’s implement our web service!

We could also do this process the other way around, instead of creating the database first we could create our entities model and create a database of it using the Entity Framework.

Submitting a high score: Implementation

Let’s go back to our HighScoreService.svc.cs file by double clicking on HighScoreService.svc, this file should look like this

namespace NielsDerdaele.HighScoreSample.WCF {    
    public class HighScoreService : IHighScoreService {        
        public void SubmitHighScore(string uniqueId, int score) {            
        }
    }
}

Let’s begin by setting up a connection to our database using the EF, to do this we will use the using statement and the model we created in the wizard before.

public void SubmitHighScore(string uniqueId, int score) {
    using (var db = new HighScoreSampleDatabaseEntities()) {

    }
}

If we want we can also provide another connection string when constructing the HighScoreSampleDatabase-Entities, but in this case we’ll use the default connection string that was chosen in the wizard above.

Now that we’ve got a connection to our database, all that’s left to do is to write our data into the correct table, we can do this in only a few lines code as listed below.

public void SubmitHighScore(string uniqueId, int score) {
    using (var db = new HighScoreSampleDatabaseEntities()) {
        db.HighScores.AddObject(new HighScore { UniqueId = uniqueId, Score = score });
        db.SaveChanges();
    }
}

Make sure you don’t forget to call db.SaveChanges()!

Retrieving all high scores

Off course we also want to retrieve the high scores in our game by calling our web service, again all we need to do is add an operation to our contract and implement the contract, but we have a little problem here, we want to return an object (not a primitive type). Your first guess might be, let’s just return the entity that was created with the wizard (so HighScore in my case), but this won’t work because WCF doesn’t know what properties need to be serialized, and even if we would just add the appropriate attributes to the properties it still wouldn’t work in all cases, so how do we solve it? The answer: Data Transfer Object.

Data Transfer Objects for the win!

For those of you who don’t know what Data Transfer Objects (DTOs) are, simply said it are objects that have as single purpose to store data (so all they have are properties/fields).

Let’s create a new class and call it HighScoreDTO. This is a very simple class with only two properties (UniqueId and Score) as shown below.

namespace NielsDerdaele.HighScoreSample.WCF {
    public class HighScoreDTO {
        public string UniqueId { get; set; }
        public int Score { get; set; }
    }
}

Remember I said before that we couldn’t return entities because WCF wouldn’t know which properties to serialize and which not. So how do we make sure WCF serialize our HighScoreDTO and all of it’s properties? First of all we need to tell WCF that we want to serialize our class, we can do this by adding the [DataContract] attribute in front of our class name and we’ll do something similar for each property we want to serialize but instead of [DataContract] we put [DataMember] in front of every property.

namespace NielsDerdaele.HighScoreSample.WCF {
    [DataContract]
    public class HighScoreDTO {
        [DataMember]
        public string UniqueId { get; set; }
        [DataMember]
        public int Score { get; set; }
    }
}

Now that we’ve got this class we can update our contract to include a function that will return all the high scores, let’s call it RetrieveHighScores.

namespace NielsDerdaele.HighScoreSample.WCF {    
    [ServiceContract]
    public interface IHighScoreService {
        [OperationContract]
        void SubmitHighScore(string uniqueId, int score);
        [OperationContract]
        HighScoreDTO[] RetrieveHighScores();
    }
}

Now all that’s left to do is to implement this new operation (just as before in the HighScoreService.svc.cs file). So we need to create a new DTO object for every HighScore entity, with LINQ this is very simple to do.

public HighScoreDTO[] RetrieveHighScores() {
    using (var db = new HighScoreSampleDatabaseEntities()) {
        return db.HighScores.Select(h => new HighScoreDTO { Score = h.Score, 
            UniqueId = h.UniqueId }).ToArray();
    }
}

Or for those of you who prefer the query syntax

public HighScoreDTO[] RetrieveHighScores() {
    using (var db = new HighScoreSampleDatabaseEntities()) {
        return (from h in db.HighScores
                select new HighScoreDTO { Score = h.Score, UniqueId = h.UniqueId }
                ).ToArray();
    }
}

Now we should be able to submit and retrieve high scores, so let’s test it. To do so: start debugging the project, this should launch the ASP.NET Development Server and open your browser when clicking on HighScoreService.svc it should render a page similar to the screenshot.

image

Now how can we test it? Normally Visual Studio should also have started an application called WCF Test Client, if it didn’t you can manually launch it by going to %ProgramFiles(x86)%\Microsoft Visual Studio 10.0\Common7\IDE\WcfTestClient.exe or %ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\WcfTestClient.exe on 32bit versions of Windows. If you start it manually just go to file –> add service and enter the endpoint address, in my case this is http://localhost:45614/HighScoreService.svc

image

Now we can call SubmitHighScore by double clicking on it, filling the required fields and pressing Invoke.

image

Add a few more entries then let’s retrieve some data, just double click on RetrieveHighScores() and press Invoke.

image

This concludes the first part, in the next part I’ll explain how we can communicate with this service from within an WP7 game/app.

Tags:

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


Manillen Online

Powered by BlogEngine.NET 2.0.0.36
Theme by Mads Kristensen | Modified by Mooglegiant