Labx

ovenforksqueeΑσφάλεια

3 Νοε 2013 (πριν από 3 χρόνια και 5 μήνες)

112 εμφανίσεις

Page |
1





Hands
-
On Lab

Building

a Social Game with Windows Azure




Lab version:

1
.0
.0

Last updated:

11/3/2013

















Page |
2



CONTENTS

OVERVIEW
................................
................................
................................
................................
........
3

EXERCISE 0: TIC
-
TAC
-
TOE
SOLO GAME

................................
................................
.........................
5

Task 1


Exploring Tic
-
Tac
-
Toe Solution
................................
................................
.........................
5

Verification


Running the Solution

................................
................................
..............................
6

EXERCISE 1: ADDING S
OCIAL PROVIDERS AND
INVITING FRI ENDS
................................
..............
8

Task 1


Configuring ACS

................................
................................
................................
..............
9

Task 2


Adding Social Gaming APIs

................................
................................
............................

11

Task 3


Creating the Login View

................................
................................
................................

18

Task 4


Creating a Friends List View
................................
................................
...........................

23

Verification

................................
................................
................................
...............................

27

EXERCISE 2: ENAB
LE MULTIPLAYER WITH
STORAGE POLLING

................................
.................

29

Task 1


Implementing Multiplayer
................................
................................
.............................

29

Task 2


Adding Worker Role to Enable Game Invitations

................................
............................

34

Task 3


Showing Game Invitation Messages from Friends

................................
...........................

35

Verification

................................
................................
................................
...............................

36

EXERCISE 3: ENABLE M
ULTIPLAYER WITH NODE
.JS
................................
................................
...

40

Task 1


Adding Node.JS Worker Role to Enable Multiplayer Games

................................
.............

40

Task 2

Implementing Multiplayer with Node.JS

................................
................................
.........

43

Task 3


Showing Game Invitation Messages from Friends

................................
...........................

47

Verification

................................
................................
................................
...............................

49

EXERCISE 4: CREATING

A LEADERBOARD

................................
................................
..................

52

Task 1


Creating the Statistics Repository Logic

................................
................................
..........

52

Task 2


Adding Statistics Entries

................................
................................
................................

56

Task 3


Creating a Leaderboard
................................
................................
................................
.

59

Verification

................................
................................
................................
...............................

63



Page |
3



Overview

Building a game has multiple challenges, more if we are building social games that require multiplayers,
contacting your friends, leaderboards and multiple ways to authenticate a user. In this lab, you will see
how to take advantage of the
Windows Azure

se
rvices benefits when building a Social Game.
Windows
Azure

offers
Access Control
service to authenticate your users using multiple Social Providers, such as
Windows Live Id

or
Facebook
. You can take advantage of
Azure Table Storage

to create a Leaderboard
or to use it as a game s
torage, where clients access
to update the game status in their browsers.
Additionally, you will see how to use
Node.JS

to emit and broadcast the players game moves to other
clients in real time.

Objectives

In this
h
ands
-
o
n
l
ab, you

will learn how to:



Add ACS Support and Invite friends



Enable Multi
-
Player using Storage Polling



Enable Multi
-
Player using Node.Js



Create a Leaderboard using Azure Table Storage



Prerequisites

The following is required to complete this hands
-
on lab:



Microsoft .NET Framework 4.0



Microsoft Visual Studio 2010



Windows Azure SDK a
nd Windows Azure Tools for Microsoft Visual Studio 1.6



ASP.NET and ASP.NET MVC 3



Microsoft® Windows Identity Foundation SDK 4.0



Microsoft® Windows Identity Foundation Runtime



Note:

This hands
-
on lab has been

designed to use the latest release of the Windows Azure Tools for
Visual Studio 2010 (version 1.
6
) and the new Windows Azure

Management

Portal experience.

Page |
4




Setup

In order to execute

the exercises in
this hands
-
on lab you need to set up your environment.

1.

O
pen a Windows Explorer window and browse to the
Source

folder.

2.

Double
-
click the
Setup.cmd

file in this folder to launch the setup process that will configure
your environment and install the Visual Studio code snippets for this lab.

3.

If the User Account Con
trol dialog is shown, confirm the action to proceed.


Note:
Make sure you have checked all the dependencies for this lab before running the setup.


Using the Code Snippets

Throughout the lab document, you will be instructed to insert code blocks. For your
convenience, most
of that code is provided as Visual Studio Code Snippets, which you can use from within Visual Studio
2010 to a
void having to add it manually.

If you are not familiar with the Visual Studio Code Snippets, and want to learn how to use them,

you can
refer to the
Assets
\
Setup.docx

document, which contains a section describing how to use them
.

Exercises

This
h
ands
-
o
n
l
ab
includ
es

the following exercise
s
:

1.

Adding Social Providers and Inviting Friends

2.

Enable Multiplayer with Storage Polling

3.

Enable

Multiplayer with Node.js

4.

Creating a Leaderboard


Estimated time to complete this lab:
9
0

minutes
.


Note:

When you first start Visual Studio, you must select one of the predefined settings collections.
Every predefined collection is designed to match a par
ticular development style

and determines
window layouts, editor behavior, IntelliSense code snippets, and dialog box options.

The procedures in
this lab describe the actions necessary to accomplish a given task in Visual Studio when using the
Page |
5



General
Development Settings

collection
. If you choose a different settings collection for your
development environment, there may be differences in these procedures that you need to take into
account.


Ex
ercise 0: Tic
-
Tac
-
Toe Solo Game

In this exercise, you wil
l explore the singl
e player Tic
-
Tac
-
Toe solution’s
structure and the logic used f
o
r

the game flow. Throughout this lab, based on this example, you will update the Tic
-
Tac
-
Toe solution to
support social gaming fe
atures for inviting friends, using

ACS and So
cial Providers to authenticate the
players

and

enabl
ing

multiplayer
mode. Finally, you will
generate a leaderboard by using Azure Table
Storage.


Task 1


Exploring Tic
-
Tac
-
Toe Solution

In this task, you will explore the Tic
-
Tac
-
Toe sample to identify the
core libraries that
uses

and how

do

they work.

1.

Start
Microsoft Visual Studio 2010

as administrator.

2.

Open the
Begin.sln

solution located at
Source
\
Ex0
-
SoloGame
\
Begin
.

3.

In the
Solution Explorer
, expand
Scripts
\
Game
\
TicTacToe

folder within
TicTacToe.Web

node

to display the core libraries used in the sample.


Figure
1

Page |
6



Game core libraries


a.

Controllers.js
: This file

handles the interaction between the view and the game logic. It
includes methods like
start
,
onMove
,
updateGameStatus
,
etc
.

b.

ViewModel.js
: This file defines the
v
iew
m
odel structure that will be used to bind the
view with the controller.

Note:
We are using the
Knockout

JavaScript library for binding our sample’s UI with
the controller logic. Knockout is a library used to simpli
fy dynamic JavaScript UIs by
applying the Model
-
View
-
View Model (MVVM) pattern. You can find more information
about Knockout library in this link:
http://knockoutjs.com/
.


c.

Board.js
: This file contains the necessary lo
gic to render the Tic
-
Tac
-
Toe board into an
HTML5 canvas.

d.

Game.js
: This class file contains the game logic, which includes player’s turns,
movements, existence of a winner, etc.

4.

Open the
Index.cshtml

view located in the
Views
\
TictacToe

folder. This view re
nders the
Tic
-
Tac
-
Toe game and interacts with the controller. Notice that this file only contains the
canvas element and the referen
ce to the JavaScript libraries.



Verification


Running the Solution

In this task, you will run the solution and play a sin
gle
-
player Tic
-
Tac
-
Toe game.

Note:
To designate the start page, in
Solution Explorer
, right
-
click the
TicTacToe.Web

project and
select
Properties
. In the
Properties

window, select the
Web

tab and in the
Start Action
, select
Specific
Page
.
S
et the value of
this field empty.


1.

In
Visual Studio
, press
F5

to build and run the solution.

2.

In the Social Gaming Sample
Home

page, click
Tic Tac Toe

in the menu to start a new single
-
player game.

Page |
7




Figure
2

Running the Tic
-
Tac
-
Toe sample


3.

Play a
new Tic
-
Tac
-
Toe game to verify the game’s flow. Then, close the browser and return
to Visual Studio.

Page |
8




Figure
3

Playing Tic
-
Tac
-
Toe, single player mode



Exercise 1: Adding Social Providers and
Inviting Friends

In this exercise,
you will use Windows Azure Access Control
S
ervice (ACS) to enable authentication in the
Tic
-
Tac
-
Toe game. The Access Control Service takes care of engaging every identity provider with its own
authentication protocol, normalizing the authentication results

in a protocol supported by the .NET
framework tooling. In order to simplify the flow of this exercise, you will add the necessary configuration
to access the existing public namespace ‘
local
-
watgames


,which is used in the
Windows Azure Toolkit
for Social

Games
. Next, you will create a view t
o

send invitations to other users and see the list of
friends you added.


Page |
9



Note:

In this exercise

you will add social gaming features, but the multiplayer mode will be added in
the following exercises.


Task 1


Configuring ACS

1.

Open the
B
egin.sln

solution located in the folder
\
Source
\
Ex1
-
ACSAndInvite
\
Begin
. You can
alternatively continue working with the solution from Exercise 0.

2.

Follow these steps
to install the
NuGet

package dependencies
.

a.

Open the
NuGet

Package

Manager Console
. To do this, select
Tools | Library Package
Manager | Package Manager Console
.

b.

In the
Package Manager Console,

type
Install
-
Package NuGetPowerTools
.

c.

After installing the package, type
Enable
-
PackageRestore
.

d.

Build

the solution. The
NuGet

de
pendencies will be downloaded and installed
automatically.

Note:
One of the advantages of using NuGet is that you don’t have to ship all the
libraries in your project, reducing the project size. With NuGet Power Tools, by
specifying the package versions in

the Packages.config file, you will be able to
download all the required libraries the first time you run the project. This is why you
will have to run these steps after you open an existing solution from this lab.

For more informa
tion
,

see this article:
http://docs.nuget.org/docs/workflows/using
-
nuget
-
without
-
committing
-
packages
.


3.

Right
-
click the
TicTacToe.Web

project and select
Add Windows Azure Deployment Project
.
This will create a Windows Azure deployment project that will host the
TicTacToe.Web

in
the Cloud.

4.

Open the
Web.config

file from the
TicTacToe.Web

project. You will next add the necessary
entries to configure ACS to use the public namespace
local
-
watgame
s
.

a.

At the top of the file, below the
configuration

root node, add the following code to
include the Windows Identity Foundation configuration section.

XML


<
configSections
>


<
section

name
=
"
microsoft.identityModel
"

type
=
"
Microsoft.IdentityModel.Configur
ation.MicrosoftIdentityModelSectio
n, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35
"

/>


</
configSections
>

Page |
10




b.

In the
appSettings

element, add the following new entries

with
key

AcsNamespace
,
ApiUrl
, and
BlobUrl
.

XML

<
add

key
=
"
AcsNamespace
"

value
=
"
local
-
watgames.accesscontrol.windows.net
"

/>

<
add

key
=
"
ApiUrl
"

value
=
"
http://127.0.0.1:81
/
"

/>

<
add

key
=
"
BlobUrl
"

value
=
"
http://127.0.0.1:10000/devstoreaccount1/
"

/>


c.

Locate the
system.web
closing node and
add
the
following code above the closing tag.

XML


<
httpRuntime

requestValidationType
=
"
Microsoft.Samples.SocialGames.Web.Security.WSFederat
ionRequestValidator
"

/>


<
httpModules
>


<
add

name
=
"
WSFederationAuthenticationModule
"

type
=
"
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35
"

/>


<
add

name
=
"
SessionAuthenticationModule
"

type
=
"
Microsoft.IdentityModel.Web.SessionAuthenticatio
nModule,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35
"

/>


</
httpModules
>


</
system.web
>


d.

Inside the
system.webServer

node, replace the
modules

node with the following code:

XML

<
modules

runAllManagedModulesForAllRequests
=
"
true
"
>


<
add

name
=
"
WSFederationAuthenticationModule
"

type
=
"
Microsoft.IdentityModel.Web.WSFederationAuthenticationModule,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35
"

preCondition
=
"
managedHandler
"

/>


<
add

name
=
"
SessionAuthenticationModule
"

type
=
"
Microsoft.IdentityModel.Web.SessionAuthenticationModule,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35
"

preCondition
=
"
managedHandl
er
"

/>

</
modules
>


e.

At the end of the file, above the closing
configuration

node, add the
Identity Model

and
the
System.Service.Model
sections copying the following code.

Page |
11



XML


<
microsoft.identityModel
>


<
service
>


<
audienceUris
>


<
add

value
=
"
http://127.0.0.1:81/
"

/>


</
audienceUris
>


<
federatedAuthentication
>


<
wsFederation

passiveRedirectEnabled
=
"
false
"

requireHttps
=
"
false
"

issuer
=
"
https://placeholder/
"

realm
=
"
https://placeholder/
"

/>


<
cookieHandler

requireSsl
=
"
false
"

/>


</
federatedAuthentication
>


<
certificateValidation

certificateValidationMode
=
"
None
"

/>


<
issuerNameRegistry

type
=
"
Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistr
y, Microsoft.IdentityModel, Version=3.5.0.0, Cult
ure=neutral,
PublicKeyToken=31bf3856ad364e35
"
>


<
trustedIssuers
>


<
add

thumbprint
=
"
C89ECEF72C2A79809509E1E294DC68485E5042CF
"

name
=
"
https://local
-
watgames.accesscontrol.windows.net/
"

/>


</
trustedIssuers
>


</
issuerNameRegistry
>


</
service
>


</
microsoft.identityModel
>


<
system.serviceModel
>


<
serviceHostingEnvironment

aspNetCompatibilityEnabled
=
"
true
"

/>


</
system.serviceModel
>



f.

Press
CTRL+S
to save the file and close it.

5.

Create a folder in the root of the
TicTacToe.Web

project and name it
Security
.

6.

Right
-
click the
Security

folder and add an existing item. Browse to the
Source
\
Assets
\
Security
folder of the lab, select
WSFederationRequestValidator.cs
, and click
Add
.



Task
2



Adding Social Gaming APIs

In this task, you w
ill add the social gaming server APIs to enable a number of features
on

your game.
This Server APIs (or Web APIs) are wrappers of a library named
SocialGames.Core
,

which contains all the
necessary logic to invite other users

to your list of friends
,
as wel
l as
other features you will
use
throughout
this lab. This library is based on the same library that is included in the
Windows Azure
Toolkit for Social Games
.

Page |
12



Note:
The APIs provided in the
Assets

folder of this lab are using the same strategy and archite
cture
than the one used in the
Windows Azure Toolkit for Social Games

projects. For more information, go
to
http://watgames.codeplex.com/
.


1.

In the
TicTacToe.Web.Azure
cloud project, open
Properties

for the
TicT
acToe.Web
role and
add a new
s
etting with
Name

DataConnectionString
,

set

Type

to
Connection

String

and
for
the
Value

choose
Windows Azure Storage Emulator
. Save and close the
Properties

page.


Figure
4

Adding a new setting


2.

Copy the
SocialGames.Core

folder located in
\
Source
\
Assets
\

in your solution folder.


Figure
5

Copying SocialGames.Core project in the solution folder


3.

You will add the Social Games core library to the Solution
. Right
-
click the so
lution node,
select
Add

and then
Add Existing Project
. Browse to the
SocialGames.Core
folder
you have
Page |
13



just copied
and
s
elect the
SocialGames.Core.csproj

file in order to ad
d the library to your
solution.

Note:

The
SocialGames.Core

is composed of four main folders:
Common
,
Entities
,
Helpers

and
Repositories
. The main logic resides in the Repositories classes.



Figure
6

SocialGames.Core project


4.

In
TicTacToe.
Web

project, a
dd

a reference to the recently added

SocialGames.Core

project.

5.

Add two new folders at the root of the Web project and name them
Services

and
Extensions

respectively.

6.

Right
-
click the
Services

folder, select
Add

and then
Add Exiting Item
. Browse to the
Source
\
Assets
\
Services

folder of this lab

and select all the files in the folder.

7.

Right
-
click the
Extensions

folder, select
Add
and then
Add Exiting Item
. Browse to the
Sou
r
ce
\
Assets
\
Extensions
folder of this lab and select all the files in the folder.

8.

The Web APIs and the Extensions you added in the previous steps requires some
dependencies that can be installed using the
NuGet Package Manager
. Right
-
click the
TicTacToe.Web

and select
Manage NuGet Packages
.

9.

Select
Online

from the left panel and then
NuG
et official package source
. In the
Search

box,
enter
Autofac
. Click the
Install

button on both
Autofac

and
Autofac ASP.NET MVC3
Integration

packages.

Page |
14




Figure
7

Installing NuGet Packages


10.

In the
Search

box, type
WebApi.All

and inst
all the package. After installing, click
Close
.

11.

Add the following references to the
TicTacToe.Web
project:
Microsoft.IdentityModel
,
Microsoft.WindowsAzure.ServiceRuntime

and
Microsoft.WindowsAzure.StorageClient
.

12.

Open
G
lobal.asax

file and r
eplace the
namespace declarations with the following:

(Code Snippet


Building a Social Game
-

Ex1 Using Namespaces


C
S)

C#

using

System.Collections.Generic;

using

System.Configuration;

using

System.Web.Mvc;

using

System.Web.Routing;

using

Autofac;

using

Autofac.Int
egration.Mvc;

using

Microsoft.ApplicationServer.Http;

using

Microsoft.IdentityModel.Tokens;

using

Microsoft.IdentityModel.Web;

using

Microsoft.IdentityModel.Web.Configuration;

using

Microsoft.Samples.SocialGames;

Page |
15



using

Microsoft.Samples.SocialGames.Common.
Storage;

using

Microsoft.Samples.SocialGames.Entities;

using

Microsoft.Samples.SocialGames.Extensions;

using

Microsoft.Samples.SocialGames.Repositories;

using

Microsoft.Samples.SocialGames.Web.Services;

using

Microsoft.WindowsAzure;

using

Microsoft.Windows
Azure.ServiceRuntime;


13.

Now that you have the Web APIs in the project, we need to register the MVC routes to point
to their address.
Locate and r
eplace the
RegisterRoutes

method
with the following:

(Code Snippet


Building a Social Game
-

Ex1 Registering Routes


C
S)

C#

public

static

void

RegisterRoutes(
RouteCollection

routes)

{


routes.IgnoreRoute(
"{resource}.axd/{*pathInfo}"
);



routes.MapServiceRoute<
GameService
>(
"game"
);


routes.MapServi
ceRoute<
AuthService
>(
"auth"
);


routes.MapServiceRoute<
UserService
>(
"user"
);


routes.MapServiceRoute<
EventService
>(
"event"
);



routes.MapRoute(


"Default"
,


"{controller}/{action}/{id}"
,


new

{ controller =
"Home"
, action =
"Index"
, id =
UrlParameter
.Optional
});

}


14.

In the
Application_Start
method, you will setup the WCF Web Api configuration and register
the core types in a Dependency Injection container using
Autofac
. To do this, replace the
Application_Start

method with th
e following code:

Note:
For more information about
Autofac
go to
http://code.google.com/p/autofac/
.


(Code Snippet


Building a Social Game
-

Ex1 Application Start


C
S)

C#

protected

void

Application_Start()

{


CloudStorageAccount
.SetConfigurationSettingPublisher((configName,
configSetter) =>


{


string

configuration =
RoleEnvironment
.IsAvailable ?

Page |
16




RoleEnvironment
.GetConfigurationSettingValue(configName) :


ConfigurationManager
.AppSettings[configName];



configSetter(configuration);


});



// Setup AutoFac


var

builder =
new

ContainerBuilder
();


this
.DependencySetup(builder);


var

container = builder.Build();



DependencyResolver
.SetResolver(
new

AutofacDependencyResolver
(container));



// Setup WCF Web API Config


var

config =
new

WebApiConfiguration
();


config.EnableTestClient =
true
;


config.CreateInstance = (t, i, h) =>
DependencyResolver
.Current.G
etService(t);


RouteTable
.Routes.SetDefaultHttpConfiguration(config);



AreaRegistration
.RegisterAllAreas();



RegisterGlobalFilters(
GlobalFilters
.Filters);


RegisterRoutes(
RouteTable
.Routes);



FederatedAuthentication
.ServiceConfigurationCreated +=
this
.OnServiceConfigurationCreated;



// Call Initializers


var

initializers =
DependencyResolver
.Current.GetServices<
IStorageInitializer
>();


foreach

(
var

initializer
in

initializers)


{


initializer.Initialize();


}

}


15.

Add the following methods at the end of the file.

(Code Snippet


Building a Social Game
-

Ex1 DependencySetup


C
S)

C#

protected

void

DependencySetup(
ContainerBuilder

builder)

{


// Cloud Storage Account


builder.RegisterInstance<
CloudStorageAccount
>(
CloudStorageAccount
.FromConfiguratio
nSetting(
"DataConnectionString"
));


Page |
17




// Queues


builder.RegisterQueue<
GameActionStatisticsMessage
>(
ConfigurationConstants
.GameActi
onStatisticsQueue)


.AsImpl
ementedInterfaces();


builder.RegisterQueue<
GameActionNotificationMessage
>(
ConfigurationConstants
.GameAc
tionNotificationsQueue)


.AsImplementedInterfaces();


builder.RegisterQueue<
InviteMessage
>(
ConfigurationConstants
.InvitesQueue)


.As
ImplementedInterfaces();



// Blobs


builder.RegisterBlob<
UserProfile
>(
ConfigurationConstants
.UsersContainerName,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();


builder.RegisterBlob<
UserSession
>(
ConfigurationConstants
.UserSessionsContainerName
,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();


builder.RegisterBlob<
Friends
>(
ConfigurationConstants
.FriendsContainerName,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();


builder.RegisterBlob<
No
tificationStatus
>(
ConfigurationConstants
.NotificationsConta
inerName,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();


builder.RegisterBlob<
Game
>(
ConfigurationConstants
.GamesContainerName,
true

/*
jsonpSupport */
)


.AsImplementedInterfaces();


builder.RegisterBlob<
GameQueue
>(
ConfigurationConstants
.GamesQueuesContainerName,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();


builder.RegisterBlob<
UserProfile
>(
ConfigurationConstants
.GamesContaine
rName,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();



// Tables


builder.RegisterTable<
UserStats
>(
ConfigurationConstants
.UserStatsTableName,
true

/* jsonpSupport */
)


.AsImplementedInterfaces();



// Repositories


builder.RegisterType<
GameActionNotificationQueue
>().AsImplementedInterfaces();


builder.RegisterType<
GameActionStatisticsQueue
>().AsImplementedInterfaces();


builder.RegisterType<
GameRepository
>().AsImplementedInterfaces();


builder.RegisterTy
pe<
IdentityProviderRepository
>().AsImplementedInterfaces();


builder.RegisterType<
NotificationRepository
>().AsImplementedInterfaces();

Page |
18




builder.RegisterType<
UserRepository
>().AsImplementedInterfaces();


builder.RegisterType<
StatisticsRepository
>
().AsImplementedInterfaces();



// Controllers


builder.RegisterControllers(
typeof
(
MvcApplication
).Assembly);



// Services


builder.RegisterType<
AuthService
>().AsImplementedInterfaces().AsSelf();


builder.RegisterType<
EventService
>().AsImpl
ementedInterfaces().AsSelf();


builder.RegisterType<
GameService
>().AsImplementedInterfaces().AsSelf();


builder.RegisterType<
HttpContextUserProvider
>().AsImplementedInterfaces().AsSelf()
;


builder.RegisterType<
UserService
>
().AsImplementedInterfaces().AsSelf();

}


private

void

OnServiceConfigurationCreated(
object

sender,
ServiceConfigurationCreatedEventArgs

e)

{


var

sessionTransforms =
new

List
<
CookieTransform
>(
new

CookieTransform
[] {
new

DeflateCookieTransform
() });



var

sessionHandler =
new

SessionSecurityTokenHandler
(sessionTransforms.AsReadOnly());



e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);

}




Task
3



Creating the Login View

In this task, you will create the Login View that l
ists the Social Providers from Access Control.

1.

Open
TicTacToeController

and add the
Authorize

decorator to the
Index
method. If an
un
authorized user tries to access the Tic

Tac

Toe view, the application will redirect the user
to the
LogOn

view.

C#

[
Authorize
]

public

ActionResult

Index()

{


return

View();

}


2.

In the
Controllers

folder, add

a new c
ontroller with the name
BaseController
.

Page |
19



3.

The
BaseController

reads the values of the addresses for the Blob and API URLs and exposes
to the View using the
Vi
ewBag
. To do this, replace the class code with the following:

(Code Snippet


Building a Social Game
-

Ex1 BaseController



C
S)

C#

using

System.Web.Mvc;


namespace

TicTacToe.Web.Controllers

{


public

class

BaseController

:
Controller


{


protected

override

void

OnActionExecuting(
ActionExecutingContext

filterContext)


{


this
.ViewBag.BlobUrl =
System.Configuration.
ConfigurationManager
.AppSettings[
"BlobUrl"
];


this
.ViewBag.ApiUrl =
System.Configuration.
ConfigurationManager
.AppSettings[
"ApiUrl"
];



base
.OnActionExecuting(filterContext);


}


}

}


4.

Create a new
c
ontroller and name it
AccountController
.

5.

Inherit
AccountController

from the
BaseController

you created in previous steps.

C#

public

class

AccountController

:
BaseController

{

...


{


6.

Add the following using
statements

in the
AccountC
ontroller
.

(Code Snippet


Building a Social Game
-

Ex1 BaseController

Using


C
S)

C#

using

System
.Threading;

using

Microsoft
.IdentityModel.Claims;

using

Microsoft.
IdentityModel
.Protocols.WSFederation;

using

Microsoft.Samples.SocialGames.Repositories;

using

Microsoft
.Samples.SocialGames.Web.Services;

using

Microsoft.Samples.SocialGames.Entities;

using

Microsoft.Samples.SocialGames;

Page |
20




7.

The
AccountController

is responsible of authenticating and reading Claims from the Identity
Provider. The user Id is then saved (or updated if already exists) into a Table Storage to be
used in the Game and in the Friends l
ist. Implement the following methods to authenticate a
user.

(Code Snippet


Building a Social Game
-

Ex1 Implementing AccountController


C
S)

C#

private

readonly

IUserRepository

userRepository;

private

IUserProvider

userProvider;


public

AccountController(
IUserRepository

userRepository,
IUserProvider

userProvider)

{


this
.userRepository = userRepository;


this
.userProvider = userProvider;

}


public

ActionResult

LogOn(
string

returnUrl)

{


return

View();

}


[
HttpPost
]

public

Action
Result

LogOn()

{


if

(
this
.Request.IsAuthenticated)


{


// Ensure user profile


var

userId =
this
.GetClaimValue(
ClaimTypes
.NameIdentifier);


var

userProfile =
this
.userRepository.GetUser(userId);


if

(userProfile ==
null
)


{


var

loginType =
this
.GetClaimValue(
ConfigurationConstants
.IdentityProviderClaimType);


userProfile =
new

UserProfile


{


Id = userId,


DisplayName =
Thread
.CurrentPrincipal.Identity.
Name ??
string
.Empty,


LoginType = loginType,


AssociatedUserAccount =


loginType.StartsWith(
"Facebook"
,
StringComparison
.OrdinalIgnoreCase) ?


this
.GetClaimValue(
ConfigurationConstants
.FacebookAccessTokenClaimType) :


string
.Empty

Page |
21




};



this
.userRepository.AddOrUpdateUser(userProfile);


}



var

effectiveReturnUrl =
this
.GetContextFromRequest();



if

(!
string
.IsNullOrWhiteSpace(effectiveReturnUrl))


{


return

Redirect(effectiveReturnUrl);


}


}



return

Redirect(
"~/"
);

}


private

string

GetContextFromRequest()

{


Uri

requestBaseUrl =
WSFederationMessage
.GetBaseUrl(
this
.Request.Url);


var

message =
WSFederationMessage
.CreateFromNameValueCollection(requestBaseUrl,
this
.Request.Form);



return

message !=
null

? message.Context :
string
.Empty;

}


private

string

GetClaimValue(
string

claimType)

{


if

(!
Thread
.Current
Principal.Identity.IsAuthenticated)


{


throw

new

InvalidOperationException
(
"User is not authenticated"
);


}



var

claimsIdentity = (
IClaimsIdentity
)
Thread
.CurrentPrincipal.Identity;



if

(!claimsIdentity.Claims.Any(c => c.ClaimType.Equa
ls(claimType,
StringComparison
.OrdinalIgnoreCase)))


{


throw

new

InvalidOperationException
(
"Claim not found: "

+ claimType);


}



return

claimsIdentity.Claims.FirstOrDefault(c => c.ClaimType.Equals(claimType,
StringComparison
.OrdinalIgnoreCase)).Value;

}


8.

In the
Account
C
ontroller
, r
ight
-
clic
k

LogOn

action method

and select
Add View
.

Name it
LogOn

and leave the default values for the remaining f
ields.

Page |
22



9.

Replace the entire code of
LogOn

view with the following code.

CSHTML

@{


ViewBag.Title = "Login";

}


<
h2
>
Login
</
h2
>


<
p
>


Login using any of the following identity providers:

</
p
>


<
div

class
="status">

</
div
>


<
table

id
="loginsTable">

</
table
>



<
script

type
="text/javascript">


function

getQueryVariable(variable) {


var

query = window.location.search.substring(1);


var

vars = query.split(
"&"
);


for

(
var

i = 0; i < vars.length; i++) {


var

pair = vars[i].split(
"="
);


if

(pair[0] == variable) {


return

pair[1];


}


}


}



jQuery(document).ready(
function

() {


var

apiURL =
"@this.ViewBag.ApiUrl"
;




$(
".status"
).text(
"Loading..."
);



var

returnUrl = getQueryVariable(
"ReturnUrl"
);



if

(returnUrl ==
null

|| returnUrl == undefined)


returnUrl =
""
;



// Get login info


$.ajax({


type:
"GET"
,


url: apiURL +
"auth/loginselector?returnUrl="

+ returnUrl,


dataType:
"json"
,


success:
function

(result) {


createLoginButtons(result);


},

Page |
23




error:
function

(req, status, error) {


alert(error);


}


});


});



// Create the login button for each
identity provider


function

createLoginButtons(loginInfoList) {


var

loginsTable = $(
'#loginsTable'
);


loginsTable.empty();



$(
".status"
).text(
""
);



$.each(loginInfoList,
function

(i, loginInfo) {


var

loginButton = $(
'<input type="button">'
);



loginButton.attr(
"value"
, loginInfo.Name);


loginButton.click(
function

() { window.location.href =
loginInfo.LoginUrl; });



var

loginsTableTd = $(
'<td>'
);


loginsTabl
eTd.append(loginButton);



var

loginsTableTr = $(
'<tr>'
);


loginsTableTr.append(loginsTableTd);



loginsTable.append(loginsTableTr);


});


}

</
script
>


The View uses JQuery to consume the Web API
AuthService

to retrieve the list of available
providers in the ACS namespace. Once the view has the list, one button is generated for each
provider to allow users select any of the available Identity providers.



Task
4



Creating a Friends List View

In this task, yo
u will create a Friends list consuming the server APIs to invite a
nd retrieve the user’s
friends.

1.

In order to interact with the Web APIs on client
-
side, you need to send a JSON request to the
Web API Url. To do this, you will use two JavaScript files that
encapsulate the calls to the
APIs. Open the
Game

folder inside
Scripts

and add
UserService.js

and
ServerInterface.js

files
from
Assets
\
Scripts

folder of this lab.

Page |
24



2.

In the
TicTacToe.Web
project, add a new V
iew named
Friends
under the
Account

folder.

3.

Replace
the entire code with the following:

CSHTML

@{


ViewBag.Title =
"Your Friends"
;


Layout =
"~/Views/Shared/_Layout.cshtml"
;

}


<
script

src
="
@
Url.Content(
"~/Scripts/jQuery.tmpl.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/knockout
-
1.2.1.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/ServerInterface.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/UserService.js"
)"

type
="text/javascript"></
script
>


<
h2
>
Your Friends
</
h2
>


<
p
>
Use this URL to invite other users:
<
span

data
-
bind
="text: inviteURL()"

/>

</
p
>


<
h3
>
Friends
</
h3
>


<
fieldset
>


<
div

data
-
bind
='template: { name: "FriendList", foreach: friends() }'

/>

</
fieldset
>


<
script

id
="FriendList"

type
="text/html">


${$data.DisplayName} <br>

</
script
>


4.

Add the following code at the bottom of the View. This code interacts with the
UserService.js

to perform JSON requests to the Web APIs. In this case, you will request for
the Friends list by callin
g the
UserService

Web API.

CSHTML

<
script

type
="text/javascript">


var

userId =
"
@
this
.ViewBag.CurrentUserId
"
;


var

BlobUrl =
"
@
this
.ViewBag.BlobUrl
"
;


var

si =
new

ServerInterface();


var

user =
new

UserService(userId, BlobUrl, si);



function

getFriends() {


user.getFriendsInfo(
function

(friends) {


window.viewModel.refreshFriends(friends);

Page |
25




},
function

(req, status, error) {


var

errorMessage;


if

(req.responseText == undefined) {



errorMessage =
"POST Error:
\
nreq:"

+ req +
"
\
nstatus:"

+ status +
"
\
nerror:"

+ error;


}


else

{


errorMessage =
"POST Error:
\
nreq:"

+ req.responseText +
"
\
nstatus:"

+ status +
"
\
nerror:"

+ error;


}


alert(errorMessage);


});


}

</
script
>

<
script

type
="text/javascript">


function

ViewModel() {


this
.user = ko.observable(userId);


this
.friends = ko.observableArray();


this
.notifications = ko.observableArray
();


this
.inviteURL = ko.observable(document.location.href +
"/?id="

+
encodeURIComponent(userId));


}



ViewModel.prototype.refreshFriends =
function

(friends) {


for

(n
in

friends)


this
.friends.push(friends[n]);


}



jQuery(document).ready(
function

() {


window.viewModel =
new

ViewModel();



ko.applyBindings(window.viewModel);


user.getFriendsInfo(


function

(friends) { window.viewModel.refreshFriends(friends); },


function

() { alert(
'Error Get Friends'
); });


});

</
script
>


5.

Open
GameService.cs
located in the
Services

folder. Replace the contents of the method
Invite

with the following code:

(Code Snippet


Building a Social Game
-

Ex1
Invite Method



C
S)

C#


[
Authorize
]


public

HttpResponseMessage

Invite(
Guid

gameQueueId,
HttpRequestMessage

request)


{

Page |
26






dynamic

formContent = request.Content.ReadAsAsync<
JsonValue
>().Result;


var

users = formContent.users !=
null

?


((
JsonArray
)formContent.users).ToObjectArray().Select(o =>
o.ToString()).ToList() :


null
;


string

message = formContent.message !=
null

?
formContent.message.Value :
nu
ll
;


string

url = formContent.url !=
null

? formContent.url.Value :
null
;



this
.gameRepository.Invite(
this
.CurrentUserId, gameQueueId, message,
url, users);



return

SuccessResponse;


}


6.

Open the
_Layout.cshtml

View located in the
Shared

folder under
Views
.

7.

Add a new menu item that points to the recently created
Friends
view.

CSHTML

<
nav
>


<
ul

id
="menu">


<
li
>
@
Html.ActionLink(
"Home"
,
"Index"
,
"Home"
,
new

{ area =
""

},
null
)
</
li
>


<
li
>
@
Html.ActionLink(
"Tic Tac Toe"
,
"Index"
,
"TicTacToe"
,
new

{ area =
""

},
null
)
</
li
>


<
li
>
@
Html.ActionLink(
"Friends"
,
"Friends"
,
"Account"
,
new

{ area =
""

},
null
)
</
li
>



</
ul
>

</
nav
>


8.

Now you will add a method in the
AccountController
to retrieve the friends to the view. The
Friends View provides you with an invitation URL, which is no more than the same Url with a
user Id as a parameter. If the Id is provided, the
Friend

relationship is saved in an Azure blob
container and it will appe
ar in your friends list.

(Code Snippet


Building a Social Game
-

Ex1 AccountController Friends


C
S)

C#

[
Authorize
]

public

ActionResult

Friends(
string

id)

{


if

(!
string
.IsNullOrEmpty(id))


{


string

currentUserId =
this
.userProvider.UserId;

Page |
27




string

inviteUserId = id;



this
.userRepository.AddFriend(currentUserId, inviteUserId);


this
.userRepository.AddFriend(inviteUserId, currentUserId);


return

RedirectToAction(
"Index"
,
"Home"
);


}



this
.ViewBag.CurrentUserId =
this
.userProvider.UserId;


return

View();

}


9.

Press
CTRL
+SHIFT+B

to build the solution.



Verification


Note:
Before you execute the solution, make sure that the start
-
up project and the start
-
up page are
set.

To set the startup project, in
Solution Explorer
, right
-
click the
TicTacToe.Web.Azure

project and select
Set as StartUp Project
.

To designate the start page, in
Solution Explorer
, right
-
click the
TicTacToe.Web

project and select
Properties
. In the
Properti
es

window, select the
Web

tab and in the
Start Action
, select
Specific Page
.
Set the value of this field empty.


1.

Press to
F5

to run the solution
.


Figure
8

Tic
-
Tac
-
Toe Home Page


Page |
28



2.

In
the

Home

page menu, click
Tic Tac Toe
. The browser will redirect you to the
LogOn

view.

3.

Select
Windows Live Id

as the identity provider.


Figure
9

Selecting an identity

p
rovider


4.

You will be redirected to the
Windows Live Id

login page.

Enter your credentials and log

o
n.
The page will redirect you back to the Tic
-
Tac
-
Toe game.

5.

Now that you are authenticated, go to the
Friends

page by clicking
Friends
link

in the menu.

6.

As this is the first time you run the application with the Web APIs, the Friends list will be
empty.
Copy the Invitation URL.


Figure
10

Copying the Invitation URL


Page |
29



7.

Open a new s
ession in
Internet Explorer

or an
In
-
Private

session by pressing
CTRL+SHIFT+P
.

8.

Paste the invitation URL in the browse and press enter. In the
LogOn

view,
log

o
n with a
different account.

9.

Go to the
Friends

page. In the
Friends

list, you will see the user id of your first account.


Figure
11

Showing the Friend’s user id


10.

Go back to the first browser session, and refresh the
Friends

page. You will see the user id of
the second account.



Exercise 2: Enable Multiplayer with
Storage Polling

In this exercise, you will enable multiplayer for the Tic
-
Tac
-
Toe using the Storage Polling approach. This
consists in querying a Blob container
for game updates and render
ing

the result in the board.
Addi
tionally, you will learn how to invite another user to play a Tic
-
Tac
-
Toe game.


Task 1


Implementing Multiplayer

In this task, you will add multiplayer features to the Tic Tac Toe view. To do th
is, you will update the
client
-
side scripts and modify the view to interact with the game service.

1.

Open the
Begin.sln

solution located in the folder
\
Source
\
Ex
2
-
A
MultiplayerPolling
\
Begin
.
You can alternatively continue working with the solution obtained by

completing Exercise 1.

Page |
30



2.

If you continued working with the solution obtained by completing Exercise 1, skip t
his step.
Otherwise, follow these
steps
to install the
NuGet

package dependencies
.

a.

Open the
NuGet

Package Manager Console
. To do this, select
Tools
| Library Package
Manager | Package Manager Console
.

b.

In the
Package Manager Console,

type
Install
-
Package NuGetPowerTools
.

c.

After installing the package, type
Enable
-
PackageRestore
.

d.

Build

the solution. The
NuGet

dependencies will be downloaded and installed
automatically.

Note:
One of the advantages of using NuGet is that you don’t have to ship all the
libraries in your project, reducing the project size. With NuGet Power Tools, by
specifying the package versions

in the Packages.config file, you will be able to
download all the required libraries the first time you run the project. This is why you
will have to run these steps after you open an existing solution from this lab.

For more informa
tion see this article:

http://docs.nuget.org/docs/workflows/using
-
nuget
-
without
-
committing
-
packages
.


3.

Open the
TicTacToeController

class located in the
Controllers

folder and

inherit
it

from
BaseController
.

C#


public

class

TicTacToeController

:
BaseController


{


...


}


4.

In

the
TicTacToe.Web
project, add the
GameService.js

file located in the
Assets
\
Scripts

folder of this lab, to the
Scripts
\
Game
folder.

5.

Expand the
TicTacToe
folder under
Scripts
\
Game
, and add the files
Controller.js

and
ViewModel.js

located in the
Assets
\
Scripts

folder of this lab. When asked, confirm to
replace the old files.

6.

Open the
Index.
cshtml

view in the
Views
\
TicTacToe

folder of the Web projec
t.

7.

Add the following references to the core client
-
side
J
ava
S
cript files.

CSHTML

<
script

src
="
@
Url.Content(
"~/Scripts/jQuery.tmpl.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/knockout
-
1.2.1.js"
)"

type
="text/javascript"></
script
>

Page |
31



<
script

src
="
@
Url.Content(
"~/Scripts/Game/ServerInterface.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/GameService.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/
User
Service.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/TicTacToe/Board.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/TicTacToe/Game.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/TicTacToe/ViewModel.js"
)"

type
="text/javascript"></
script
>

<
script

src
="
@
Url.Content(
"~/Scripts/Game/TicTacToe/Controller.js"
)"

type
="text/javascript"></
script
>


8.

Add the following code at the beginning of the
div
element with Id
game
. This
code renders
the Invitation URL and the list of players that are in the queue waiting to play.

CSHTML


<
div

style
="
display
: none"

data
-
bind
="visible: gameQueueId() != null">


<
fieldset
>


<
legend
>
Player
</
legend
>


<
div
>



Welcome
<
b
><
span

data
-
bind
='text: playerName()'></
span
></
b
>


</
div
>


<
div

data
-
bind
="visible: isOwner() && gameQueueId() != null &&
gameId() == null">


<
span
>
Use this URL to invite other players:
<
span

data
-
bind
="text:
inviteURL()"

/>


</
span
>


<
br

/>


<
div

data
-
bind
="visible: friends() != null && friends().length >
0">


Your Friends


<
select

id
="friends"

data
-
bind
="options:
friends, optionsValue:
'Id', optionsText: 'DisplayName'">


</
select
>


<
a

href
="#"

data
-
bind
="click: inviteFriend">
Invite Friend
</
a
>


</
div
>


</
div
>


<
br

/>


<
div

data
-
bind
="visible: noPlayers() == 1 && isOwner()">


<
span
>
Waiting for your opponent...
</
span
>


</
div
>


</
fieldset
>


</
div
>


<
div

style
="
display
: none"

data
-
bind
="visible: gameQueueId() != null">

Page |
32




<
fieldset
>


<
legend
>
Players
</
legend
>


<
div

data
-
bind
='template: { name: "queueStatus", foreach: players()}'

/>


<
script

id
="queueStatus"

type
="text/html">


<li><b>${$data.UserName}</b></li>


</
script
>


</
f
ieldset
>


</
div
>


9.

Locate the
div
which
contains the legend
Game
,

and
replace it with the following:

CSHTML


<
div

style
="
display
: none"

data
-
bind
="visible: gameId() != null">


<
fieldset
>


<
legend
>
Game
</
legend
>


<
div
>


You are
<
span

data
-
bind
="visible: playerColor() ==
TTTColor.Cross">
Xs
</
span
>

<
span


data
-
bind
="visible: playerColor() ==
TTTColor.Circle">
Os
</
span
>


</
div
>


<
div

data
-
bind
="visible: playerColor() ==
currentColor()">


Your turn!
</
div
>


<
div

data
-
bind
="visible: playerColor() != currentColor()">


Opponent turn!
</
div
>


<
div

data
-
bind
="visible: isTie()">


Tie!!
</
div
>


<
div

data
-
bind
="visible: playerColor() == winnerColor()">


You won!!
</
div
>


<
div

data
-
bind
="visible: playerColor() != winnerColor() &&
winnerColor() != TTTColor.Empty">


You lose!!
</
div
>


<
canvas

id
="board"

wi
dth
="300"

height
="300"></
canvas
>


</
fieldset
>


</
div
>


10.

Locate the
script
block and insert the following code at the beginning.

javascript


var

viewModel;


var

gameQueueId = getQueryVariable(
"id"
);


var

nullGameId =
"00000000
-
0000
-
0000
-
0000
-
000000000000"
;



function

getQueryVariable(variable) {


var

query = window.location.search.substring(1);

Page |
33




var

vars = query.split(
"&"
);



for

(
var

i = 0; i < vars.length; i++) {


var

pair = vars[i]
.split(
"="
);


if

(pair[0] == variable) {


return

pair[1];


}


}


}



var

apiURL =
"
@
this
.ViewBag.ApiUrl
"
;


var

blobURL =
"
@
this
.ViewBag.BlobUrl
"
;




var

si =
new

ServerInterface();


var

gs =
new

GameService(apiURL, blobURL, si);


var

user =
new

UserService(apiURL, blobURL, si);



11.

Next to the previously inserted code, add the following:

javascript

function

start(userId) {


// check for canvas, show an "Upgrade your browser" screen if they
don't have
it.


var

canvas = document.getElementById(
'board'
);


if

(canvas.getContext ==
null

|| canvas.getContext(
'2d'
) ==
null
) {


$(
"#game"
).toggle();


$(
"#notSupported"
).toggle();



return
;


}



var

board =
new

TicTacToeBoard(canvas);


var

game =
new

TicTacToeGame();


var

controller =
new

TicTacToeController(viewModel, gs, board, game);



controller.setGameQueueId(gameQueueId);


controller.start();


user.getFriendsInfo(
function

(friends) { viewMod
el.friends(friends); });


user.getUser(userId,
function

() { });



window.onbeforeunload =
function

() { controller.finish(); };

}


12.

Replace the body of the
$(function ())

method with the following.

Page |
34



javascript


$(
function

() {


viewModel =
new

TicTacToeViewModel();


ko.applyBindings(viewModel);



user.verify(


function

(userId) { start(userId); },


function

() {


var

newlocation =
'
@
Url.Action(
"LogOn"
,
"Account"
,
new

{ Area =
""
, ReturnUrl =

"replace
-
in
-
js"

})
'
;


newlocation = newlocation.replace(
"replace
-
in
-
js"
,
encodeURIComponent(window.location.href));


window.location.assign(newlocation);


}


);


});


13.

Add the following two methods to the
script block.

javascript


function

inviteFriend() {


var

userId = $(
"#friends"
).val();


var

userName = $(
"#friends :selected"
).text();


gs.inviteUser(viewModel.gameQueueId(), userId,
"Invitation for Tic Tac
Toe"
, viewModel.inviteURL
(),
function

() { alert(userName +
" was invited"
) });


}



function

sgusersCallback(user) {


if

(user.DisplayName !=
null

&& user.DisplayName !=
""
)


viewModel.playerName(user.DisplayName);


else


viewModel.playerName(user.Id);


}



Task 2


Adding Worker Role to Enable Game Invitations

In this task, you will add an existing project that will be in charge of processing invitation requests.

1.

Copy the folder

\
S
ource
\
Assets
\
SocialGames.Wo
rker

to the root of your project folder.

Page |
35




Figure
12

Copying the worker to the project folder


2.

Add the project
SocialGames.Worker.csproj

located
in the folder you copied
(
\
SocialGames.
Worker
\
)

to the
s
olution.

3.

In the
TicTacToe.Web.Azure
cloud project, associate the recently added project as a Worker
Role in the
Roles

folder.

4.

Open the role
Properties

for the
SocialGames.Worker
and add a new s
etting with
Name

DataConnectionString
,

set the

Type

to
Connection String

and

fo
r

Value

choose
Windows
Azure Storage Emulator
. Save and close the
Properties

page.


Task 3


Showing Game Invitation Messages from Friends

In this task, you will update the
Friends

view to show the invitation messages from other users.

1.

Open the
Friends

vie
w located in
Views
\
Account

folder of the Web project.

2.

Add the
Invitations
table below the
script

block with id
FriendList
.

javascript

<
h3
>
Invitations
</
h3
>

<
table
>


<
thead
>


<
tr
>


<
th
>
Message
</
th
>


<
th
>
From
</
th
>


<
th
>
Action
</
th
>


</
tr
>


</
thead
>


<
tbody

data
-
bind
='template: { name: "NotificationList", foreach:
notifications() }'

/>

</
table
>


Page |
36



<
script

id
="NotificationList"

type
="text/html">

<tr>


<td>${$data.Message} </td>


<td>
${$data.SenderName} </td>


<td><a href="${$data.Url}">Go</a> </td>

</tr>

</
script
>


3.

Add a call to the
user.getNotifications
method
at the end of
jQuery

ready

function within
the script block
in order to retrieve the game invitation messages.

javascript


jQuery(document).ready(
function

() {


window.viewModel =
new

ViewModel();



ko.applyBindings(window.viewModel);


user.getFriendsInfo(


function

(friends) { window.viewModel.refreshFriends(friends); },


function

() { alert(
'Error Get Friends'
); });



user.getNotifications(userId,
function

() { });


});


4.

Add a callback method at the end of the block script. This method is used by the
UserService
to return the invitation messages.

javascript


function

sgnotificationsCallback(data) {


for

(
var

n
in

data.Notifications) {


var

notification = data.Notifications[n];



if

(notification.SenderName ==
null

|| notification.SenderName ==
""
)


not
ification.SenderName = notification.SenderId;



if

(notification.Type ==
"Invite"
)


viewModel.notifications.push(notification);


}


}




Verification


Page |
3
7



Note:
Before you execute the solution, make sure that the start
-
up project and the start
-
up page are
set.

To set the startup project, in
Solution Explorer
, right
-
click the
TicTacToe.Web.Azure

project and select
Set as StartUp Project
.

To designate the start pag
e, in
Solution Explorer
, right
-
click the
TicTacToe.Web

project and select
Properties
. In the
Properties

window, select the
Web

tab and in the
Start Action
, select
Specific Page
.
Set the value of this field empty.


1.

Press to
F5

to run the solution
.

2.

Click the

Tic Tac Toe

menu link and log

o
n with an identity provider. You will see the current
list of Players that are in the same game queue. Additionally, an invitation URL will be
generated. Copy this URL.


Figure
13

Listing players
and the auto generated invitation URL


3.

Open a new session in
Internet Explorer

or an
In
-
Private

session by pressing
CTRL+SHIFT+P

without closing the current one
.

4.

Paste the invitation URL. When prompted, enter other credentials to log

o
n. Now, the list of
p
layers will show both users. Check the first browser to verify that both users are listed as
well.

Page |
38




Figure
14

Playing a multiplayer Tic
-
Tac
-
Toe


5.

Start playing the game. You will see how the browsers are updated after each move.

6.

Re
start the game by clicking the
Tic Tac Toe

menu link in the first browser. You will see a
new drop
-
down list

that shows you
r

friends.

Page |
39




Figure
15

Listing friends


7.

Click the
Invite Friend

link. A confirmation message will appear. Cl
ick
OK
.


Figure
16

Invite a friend confirmation


8.

In the second browser, click the
Friends

link. The
Invitations

table will show a new message
from the other user. The message has a link that takes you to the Tic Tac Toe page with the
game queue Id. Click the
Go

link.

Page |
40




Figure
17

Invitation Message


9.

The link takes you to the Tic Tac Toe page

and a new game will be started.

10.

Close the browsers.



Exercise 3: Enable Multiplayer with
Node.Js

In
this exercise, you will enable multiplayer for the Tic
-
Tac
-
Toe game using a different approach than the
one from Exercise 2. Instead of querying the storage for updates, you will start a
Node.JS

Worker Role
node that enables co
mmunication between Web clien
ts by

broadcasting incoming messages between
connected clients. To do this, Node.JS uses a module named
Socket.IO

that opens Web Sockets between
the client browser and the Node server. This way, the client browser
emits

a message to the Server,
which is th
en
broadcasted

to other clients (in this case, the other player’s browser).

To enable multiplayer,
Node.JS

and
Socket.IO

allows you to send the game’s actions to the other player
in real
-
time, without n
eeding to poll the game status.


Task 1