About the Author

Xen is a Software Engineer at InterKnowlogy, located in Carlsbad, CA. She is a proud alumni of Utah’s Neumont University, known for its’ accelerated programs with focus on technology-based courses and curriculums. With a degree in Computer Science, Xen has experience with both Web and desktop application development that involve technologies including ASP.net MVC, Windows Presentation Foundation (WPF), CSS, HTML and JavaScript. Since working with the InterKnowlogy crew, Xen has been introduced to Windows Runtime (WinRT), Windows Phone and Kinect development. Aside from being tech savvy, Xen is a snowboarder, likes to hike, play basketball, volleyball and is willing to try any outdoor activity there is. Follow her on twitter @xnarie20

Querying Entities from Azure Storage Tables using Javascript

After enabling the Azure storage to allow cross-origin requests using CORS. Now we are ready to query the storage entities using Javascript.

Know the URL

We start off by reading Microsoft Azure post about querying entities. According to the post, we can make a GET request to the Azure table using:

var urlPath = https://{accountName}.table.core.windows.net/{mytable}(PartitionKey='<partition-key>',RowKey='<row-key>')?$select=<comma-separated-property-names>
  • Partition key and Row key are used to query a specific entity.
  • The select query is used to filter on that specific column. (e.g.$select=timestamp will grab the entities’ timestamp).

Build the Signature

As reference, Microsoft Azure’s blog about Authentication for the Azure Storage Services, it shows what we need to construct the Signature String.
The formula to build the signature is Signature=Base64(HMAC-SHA256(UTF8(StringToSign)))

Things To Know:

  • Shared Key Lite Authentication (Table Service) has a Signature String:

    StringToSign = Date + "\n" 
                   CanonicalizedResource
    

    Shared Key Authentication (Table Service) has a Signature String:

    StringToSign = VERB + "\n" + 
                   Content-MD5 + "\n" + 
                   Content-Type + "\n" +
                   Date + "\n" +
                   CanonicalizedResource;
    
  • Canonicalized Resource has a format of: “/{accountname}/{query string}
    For example, If you want to call a GET request on:

    https://myaccount.table.core.windows.net/mytable()?$filter=<query-expression>&$select=<comma-separated-property-names>
    

    The query string is: mytable() [do not include anything after ‘?’]. So the Canonicalized Resource will be: /myaccount/mytable()

  • Secret Key:
    Log in to your Microsoft Azure Portal -> Select the Storage account you want -> Manage Access Keys -> Primary Access Key or Secondary Access Key
  • Lastly, the most confusing of all, encrypting the Signature String and Secret Key to form the Signature
    For encryption, I used Crypto-JS.
    Basically, we need to perform SHA-256 hash to produce the signature. Using Crypto-JS, it will be:

    var signature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(CryptoJS.enc.Utf8.parse(stringToSign), CryptoJS.enc.Base64.parse(secretKey)));
    

Request Headers

There are only 2 required request headers when doing a request to Microsoft Azure:

  • Authorization=”[SharedKey|SharedKeyLite] {AccountName}:{Signature}”
    (e.g. Authorization: SharedKeyLite testaccount1:uay+rilMVayH/SVI8X+a3fL8k/NxCnIePdyZSkqvydM=)
  • Date or x-ms-date – make sure it’s in UTC.

Optional:

  • x-ms-version – version of the operation for the request.
  • Accept – content type of the response payload.
    • application/atom+xml
    • application/json;odata=nometadata
    • application/json;odata=minimalmetadata
    • application/json;odata=fullmetadata

In Action…

So using JQuery ajax, we call:

$.ajax({
		url: urlPath,
		type: 'GET',
		success: function (data) {
			//do something to data
		},
		beforeSend: function (xhr) {
			xhr.setRequestHeader('Authorization', "SharedKey " + accountName + ":" + signature);
			xhr.setRequestHeader('x-ms-date', dateInUTC);
			xhr.setRequestHeader('x-ms-version', '2014-02-14');
			xhr.setRequestHeader('Accept', 'application/json;odata=nometadata');
			xhr.setRequestHeader('DataServiceVersion', '3.0;NetFx');
			xhr.setRequestHeader('MaxDataServiceVersion', '3.0;NetFx');
		},
		error: function (rcvData) {
			console.log(rcvData);
		}
	});

And you are done! Happy Coding.

What is CORS?

There are lots of instances that an app will need to call a GET/POST request to another domain (from a different domain where the resource originated). Once the web app starts doing the request, the response will throw an “Access-Control-Allow-Origin” error. Then you ask yourself, what now?

One solution is CORS (Cross-origin resource sharing), which allows all resources (like JavaScript) to make cross origin requests.
Here is an example of how to add CORS Rule to allow a request to Azure storage tables using Azure SDK.

1. Build the connection string

string connectionString= "DefaultEndpointsProtocol=https;
AccountName={account name/storage name};
AccountKey={PrimaryKey|SecondaryKey}";

2. Create the CloudTableClient

CloudStorageAccountstorageAccount = CloudStorageAccount.Parse( connectionString);
CloudTableClient client = storageAccount.CreateCloudTableClient();

3. Add CORS Rule
* as wildcard

CorsRule = new CorsRule()
{
  AllowedHeaders = new List<string> { "*" },
  AllowedMethods = CorsHttpMethods.Connect | CorsHttpMethods.Delete | CorsHttpMethods.Get | CorsHttpMethods.Head | CorsHttpMethods.Merge
	| CorsHttpMethods.Options | CorsHttpMethods.Post | CorsHttpMethods.Put | CorsHttpMethods.Trace, 
  //Since we'll only be calling Query Tables, let's just allow GET verb
  AllowedOrigins = new List<string> { "*" }, //This is the URL of our application.
  ExposedHeaders = new List<string> { "*" },
  MaxAgeInSeconds = 1 * 60 * 60, //Let the browswer cache it for an hour
};

4. Add rules to client

ServiceProperties serviceProperties = client.GetServiceProperties();
CorsProperties corsSettings = serviceProperties.Cors;
corsSettings.CorsRules.Add( corsRule );
//Save the rule
client.SetServiceProperties( serviceProperties );
  • After #4, there should already be cors rule connected to an account name.
    In order to double check what cors rules are there for that account name, we can use:

    ServiceProperties serviceProperties = client.GetServiceProperties();
    CorsProperties corsSettings = serviceProperties.Cors;
    

NOTE: If we need to put cors rule for blobs, we will just change CreateCloudTableClient():
CloudBlobClient client = storageAccount.CreateCloudBlobClient();

ASP.NET MVC5 + Twitter Bootstrap

Creating an ASP.NET MVC 5 Project

Model-View-Controller (MVC) is a software architectural pattern that divides software application into three parts.
Model consists of the business logic and functions.
View is the representation of the information. These information can be illustrated through graphs or charts or any of the user interface that the user interacts with.
Controller receives input from view and model.

1. Visual Studio -> New -> Project -> Under Web -> ASP.NET Web Application
2. Choose MVC template — this will create a default template with MVC folders.
Another template is Web API which will add API folder for REST HTTP calls.
ChoosingWebApi
3. Run the app to make sure it’s compiling and building properly.

Twitter Bootstrap 3 Discovery

What is Twitter Bootstrap? Twitter Bootstrap is an open-source tool that helps in creating websites or web applications. This tool includes pre-developed HTML and CSS templates for arranging html components (Grid-System), forms, buttons, charts, and other navigation components that we normally see in a responsive web application.

Some PROS of Twitter Bootstrap:

  • CONSISTENCY
    Who would not want to see a consistent font and style within a web page? Both developers and users would want to see a consistent flow in a project, so Twitter Bootstrap was built to avoid a confusing layout flow in every web page that users will interact.
  • RESPONSIVE
    Whether it is a huge desktop, a really small mobile screen or a phone with a size like a tablet, Twitter Bootstrap got it covered! This tool is developed to have a responsive layout that caters to all the different screen sizes that any user may have.
  • LATEST AND GREATEST
    Twitter Bootstrap was made by really great developers who used the latest libraries out there: CSS3, HTML5, JQuery… etc. The CSS was developed using LESS platform that allows using variables, mixins, functions inside the CSS page to make CSS more themable and extendable.

By default, MVC5 is using the Twitter Bootstrap template by default. That means, the bootstrap.min.js and bootstrap.min.css are already inside the project and we do not need to download it from Twitter Bootstrap’s webpage to use it’s styles.

Grid System

  • Twitter Bootstrap makes the page responsive to phone/tablet/desktop by adding the viewport meta tag:
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
  • Twitter Bootstrap’s grid system scales up to 12 columns.
    This means that all the columns with .col-md-* should add up 12. Any columns after the 12th will be stacked underneath the first 12.
  • Rows are placed inside a class .container for proper alignment.
    <div class="container">...</div>
    
  • Use class .row to create horizontal column groups.
  • Columns are created specifying the number that can add up to twelve. For example, four proportionally sized columns would be: four div with class .col-md-3
    XS = Phones, SM = Tablets, MD = Desktops, LG = Large Desktops
  • GridSystemTable

NOTE: As the browser widens, the smaller-sized classes gets overwritten. As the browser contracts, the larger classes are overwritten.

<div class="row">
    <div class="col-xs-6 col-md-6 col-sm-6">col-xs-6 col-md-6 col-sm-6</div>
    <div class="col-xs-6 col-md-6 col-sm-6">col-xs-6 col-md-6 col-sm-6</div>
</div>
<div class="row">
    <div class="col-xs-4 row-grid">col-xs-4</div>
    <div class="col-xs-4 row-grid">col-xs-4</div>
    <div class="col-xs-4 row-grid">col-xs-4</div>
</div>
<div class="row">
    <div class="col-md-3">col-md-3</div>
    <div class="col-md-3">col-md-3</div>
    <div class="col-md-3">col-md-3</div>
    <div class="col-md-3">col-md-3</div>
</div>
<div class="row">
    <div class="col-xs-8 col-md-8 col-sm-8">col-xs-8 col-md-8 col-sm-8</div>
    <div class="col-xs-4 col-md-4 col-sm-4">col-xs-4 col-md-4 col-sm-4</div>
</div>

Other Good Stuff…

Offsetting columns

To move columns to the right, use “.col-*-offset-*”. The first * depends on the screen size which could be written as “.col-xs-offset-, .col-md-offset-, or .col-sm-offset-“. The second * increases the left margin of column by * columns. For example, “.col-md-offset-4” moves that column over four columns.
offset
As we can see on this example, we could combine the class names “.col-md-4” and “.col-md-offset-3” which defines the width of the column then offsets the column to 3 columns (-offset-3).

Like the grid system example, the offsets follow the 12-column way of how the columns are arranged. An example would be doing “.col-md-4” followed by a div with “.col-md-4 .col-md-offset-4”. Where will the second div be?
nested-offset
So, since the position of the second div (without the -offset-4) is beside the first div, the offset made it so it moved another 4 columns over.

<div class="row">
    <div class="col-md-4">.col-md-4</div>
    <div class="col-md-4 col-md-offset-4">.col-md-4 .col-md-offset-4</div>
</div>
<div class="row">
    <div class="col-md-3 col-md-offset-3">.col-md-3 .col-md-offset-3</div>
    <div class="col-md-3">.col-md-3</div>
</div>

Nesting columns

Inside the .row, we can add a set of .col-md-* inside of an exisiting .col-md-*. To visualize it properly…
nested-row

<div class="row">
    <div class="col-md-9">
        1st row .col-md-9 (Parent Row)
        <div class="row">
            <div class="col-md-6">
                Nested 2nd row .col-md-6
            </div>
            <div class="col-md-6">
                Nested 2nd row .col-md-6
            </div>
        </div>
    </div>
</div>

For this example, the parent row (with a class .col-md-9) has a 9 column-width. Since the next row is nested (with 2 .col-md-6) that add up to 12-columns, their TOTAL WIDTH will only extend up to 9 columns (not 12), but they will be evenly divided because both of them add up to 12 columns.
What I mean by that is…
NestedAndNonNestedRows

<div class="row">
    <div class="col-md-9">
        1st row: .col-md-9
        <div class="row">
            <div class="col-md-6">
                2nd row (Nested): .col-md-6
            </div>
            <div class="col-md-6">
                2nd row (Nested): .col-md-6
            </div>
        </div>
    </div>
</div>
<div class="row">
    <div class="col-md-6">
        (Not Nested) .col-md-6
    </div>
    <div class="col-md-6">
        (Not Nested) .col-md-6
    </div>
</div>

IMPORTANT: Nested rows (even when the column-set adds up to 12 columns) follow the max width of the parent row unlike a non-nested row that can span out to 12-column width.

Push and Pull Columns (Column Ordering)

We use the modifiers .col-md-push-* and .col-md-pull-* to change the order of the grid columns.

<div class="row">
    <div class="col-md-9 col-md-push-3">1st column (col-md-push-3)</div>
    <div class="col-md-3 col-md-pull-9">2nd column (col-md-pull-9)</div>
</div>

This code results to:
pushpullTB

For this example, we can see that we pushed the 1st column to 3 columns to the right and pulled the 2nd column 9 columns to the left. Since the columns are also 9 and 3 column-width respectively, they just switched places.
IMPORTANT: In other words, we use -push- and -pull- to re-organize our column positions. Unlike offsets, when we “push” a column, it does not affect the position of any other column beside it. For example, if there are 2 columns, and only the first column has a “-push-*” class, the 2nd column will stay in the same place and will not be pushed to the right. Offset, on the other hand, pushes everything to the right of the column that has the -offset-* class.

References:

Twitter Bootstrap 2.3.2
Twitter Bootstrap 3

Windows Services: File Watcher Implementation

File Watcher

File Watcher is an application that continuously monitor your files. You can define files or a whole directory to look after, and have a custom action that notifies you every time those files/directory have been changed (created, deleted, renamed or error had occurred).

Simple Implementation Steps:

1. Create a new FileWatcher and define values for its properties

FileWatcher watcher = new FileWatcher();
watcher.Path = Path.GetDirectoryName(file); 
watcher.Filter = Path.GetFileName(file);
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
           | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  • Path of the directory to be monitored.
  • Filter: “.txt” only watch text files, “GetFileName(file)” only watch that specific file.
  • NotifyFilter: watch for changes in LastAccess, LastWrite, FileName, DirectoryName

2. Subscribe to Event Handlers
These will notify the user if there are changes to the file/directory the FileWatcher is watching.

watcher.Changed += FileChanged;
watcher.Renamed += FileRenamed;
watcher.Created += FileChanged;
watcher.Deleted += FileChanged;
private void FileRenamed( object sender, RenamedEventArgs e )
{
 Debug.WriteLine( string.Format( " {0} renamed to {1} at {2}", e.OldFullPath, e.FullPath, DateTime.Now.ToString( "MM/dd/yy H:mm:ss" ) ) );
}

private void FileChanged( object sender, FileSystemEventArgs e )
{
 Debug.WriteLine( string.Format( "{0} with path {1} has been {2} at {3}", e.Name, e.FullPath, e.ChangeType, DateTime.Now.ToString( "MM/dd/yy H:mm:ss" ));
}

3. Enable the FileWatcher.
NOTE: When Path is not set and EnableRaisingEvent is not set to true, specified file/directory will not be watched.

watcher.EnableRaisingEvents = true;

FileWatcher + Windows Services

Windows Services allows us to run assembly in the background. They are very suitable for the times when you need to continuously listen to incoming network connections, or monitor a directory or files.
Let’s make a Windows Service project by doing File -> New Project -> Windows Service
Do not forget to inherit from ServiceBase().

  • By default, we already have the Run() in Program.cs that creates an instance of our FileWatcherService class.
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
       {
          new FileWatcherService()
       };
    ServiceBase.Run(ServicesToRun);
    
  • When we start our service, the service will call the OnStart() inside our FileWatcherService().

  • Like what was described above this post, we create an instance of the FileWatcher on OnStart() and subscribe to the events.
    OnStop(), we dispose the FileWatcher instance and unsubscribe to the events.

    protected override void OnStart( string[] args )
    {
    _fileWatcher = new FileWatcher( currentDirectory );
    _fileWatcher.Changed += FileChanged;
    _fileWatcher.EnableRaisingEvents = true;
    }
    
    protected override void OnStop()
    {
    _fileWatcher.Changed -= FileChanged;
    _fileWatcher.EnableRaisingEvents = false;
    _fileWatcher.Dispose();
    }
    
  • a. Create an Installer: Add -> new Class
    b. After creating a new class, inherit the class from Installer [add reference to System.Configuration.Install]
    c. Create a new ServiceProcessInstaller() and ServiceInstaller — These install an executable that extend ServiceBase(), which is our FileWatcherService.
    d. Set the properties: ServiceName, Account, StartType, DisplayName, etc.
    NOTE: Set the ServiceName to be the same as the value of the ServiceName on the service itself.
    e. Add the 2 installers to the Installers collection.

    ServiceProcessInstaller processInstaller = new ServiceProcessInstaller();
    ServiceInstaller serviceInstaller = new ServiceInstaller();
    processInstaller.Account = ServiceAccount.NetworkService;
    serviceInstaller.DisplayName = "File Watcher Service";
    serviceInstaller.StartType = ServiceStartMode.Manual;
    serviceInstaller.ServiceName = "File Watcher Service";
    Installers.AddRange(new Installer[]
    {
      processInstaller, serviceInstaller
    });
    
  • Install the service and start running it!
    a. Run Command Prompt [Visual Studio Command Prompt or Windows SDK Command Prompt] as Administrator.
    b. Go to the directory where the Windows Service executable is at.
    c. Type installutil {name of the service} (e.g. installutil FileWatcherService.exe).
    d. On Success, you will be able to see the Service on your Local Services list.
    Windows Service

    Windows Service successfully installed


    e. To uninstall: type installutil /u {name of the service}

Simple Steps to FTP Upload Files

File Transfer Protocol (FTP) is a network protocol used to transfer files between computers and networks.
The FTP Url designates a file or a directory on an Internet Host that is accessible using FTP Protocol.
Normally, FTP Url is formatted: “ftp://”+ username + host + port + directory + filename

The syntax of FTP Url includes:

  • Host – fully qualified domain name of network host or IP Address (e.g. 172.0.0.1)
  • Port number to connect to – NOTE: if omitted, it defaults to 21
  • Username (user id) on the host
  • Password corresponding to the username

Here is a simple way to upload file to an FTP server:
1. Create an FtpWebRequest and pass in your FTP Url

FtpWebRequest ftpClient = (FtpWebRequest)FtpWebRequest.Create( "ftp://" + ftpPath + "/" + filename);
ftpClient.Credentials = new NetworkCredential( ftpUserName, ftpPassword );
ftpClient.Method = WebRequestMethods.Ftp.UploadFile;
ftpClient.UseBinary = true;
ftpClient.KeepAlive = true;
ftpClient.ContentLength = file.Length;

2. Copy the contents of the file to the request stream using GetRequestStream().
Do not forget to close the Stream.

Byte[] buffer = new byte[file.Length + 1];
int bytes = 0;
int totalBytes = (int)file.Length;
FileStream fileStream = file.OpenRead();

Stream stream = ftpClient.GetRequestStream();
while ( totalBytes > 0 )
{
bytes = fileStream.Read( buffer, 0, buffer.Length );
stream.Write( buffer, 0, bytes );
totalBytes = totalBytes - bytes;
}
 //fs.Flush();
fileStream.Close();
stream.Close();

3. To finish the process, we need to close the ftpClient’s WebResponse.

FtpWebResponse uploadResponse = (FtpWebResponse)ftpClient.GetResponse();
uploadResponse.Close();

Error Handling and other Gotcha’s

  • It is important we surround our code with try catch block because we need to make sure we protect the users from Exceptions like invalid credentials, etc.
    This is handled using the ftpClient’s response’s StatusCode

    catch ( WebException ex )
    {
        FtpWebResponse response = (FtpWebResponse)ex.Response;
        switch ( response.StatusCode )
           {
              case FtpStatusCode.NotLoggedIn:
              Debug.WriteLine = "You entered invalid username/password. Try again.";
              break;
    
              default:
              Debug.WriteLine = "The server is inaccessible or taking too long to respond.";
              break;
            }
    }
    
  • When creating FtpWebRequest and giving it the path (for example): “ftp://host:port/{directoryName}/{filename}, we need to make sure that {directoryName} has been created/should exist or it will throw an exception on GetRequestStream().

    Example:

    1. Create the directory, first.

     string directoryPath = "ftp://" + ftpPath + "/" + directory.Name;
     try
       {
        var request = (FtpWebRequest)FtpWebRequest.Create( directoryPath );
        request.Method = WebRequestMethods.Ftp.MakeDirectory;
        request.Credentials = new NetworkCredential( ftpUserName, ftpPassword );
        var uploadResponse = (FtpWebResponse)request.GetResponse();
        uploadResponse.Close();
       }
    

    2. Create FtpWebRequest and include directory to file path.

     var ftpClient = (FtpWebRequest)FtpWebRequest.Create( "ftp://" + ftpPath + "/"+ directory.Name + file.Name);
    

Telestr8: Introduction and Features

Introduction

Telestr8 is a desktop application that has a sole purpose of annotating images shared by Telestr8 Mate or any image shown in the desktop. At the end of every session, all images are stored in a folder in Picture Library (as .png) for future use.

As I mentioned on my previous blog post, Telestr8 works closely with Telestr8 Mate that it is important that Telestr8 is installed in one device and Telestr8 Mate is running on another device for them to communicate. From Telestr8 Mate, we can share images to Telestr8 and these shared images will be displayed in a panel on the top-right of Telestr8.

Card Panel where all shared and duplicated images are found

Feature: Desktop Mode

Telestr8_DesktopMode

Things you can do on desktop mode:

a) Toggle annotation mode on/off – This mode will allow you to annotate on any image you selected.
b) Duplicate your desktop image and add it to your card panel

  • This means you can take a screenshot of your desktop so you can annotate on it.
  • This will then be added to your card panel for future use.

c) View any connections (IP Address) your device is connected to.
d) Help menu – You will be able to read 3 pages worth of documentation on how to use the menu of Telestr8 (like this blog post, but more detailed).
e) Exit Telestr8

Feature: Annotation Mode

Telestr8_AnnotationMode


Once annotation is toggled on, a screenshot of your desktop will be added to the collection of images in your card panel.

Things you can do on Annotation Mode:

a) Select brush size and brush color for annotating.
b) Toggle erase on/off
c) Erase all annotations (strokes, etc.) on the image you are working on.
d) Create a copy of the image you are currently working on and automatically add it to the collection of images you have on your card panel.
e) View help menu
f) Done annotating! – Saves all the strokes or any changes made on that image replacing its original image.

Favorite Feature

  • While working on this application, I have 2 main features I can call my “favorite”:
    1) Being able to save on clipboard with an animation to show you did, and
    2) On Exit, the animation of showing all of the images stored in your card panel and one by one getting moved out of the view mode then at the end of the process, all of it are display in the photos library with all of the images saved as PNG files.
  • These features are accomplished by using Storyboard’s DoubleAnimation and also using Blend to do fluid layout. Both features have very challenging animations that once you get the hang of it, it becomes very easy to deal with.

Introducing Telestr8 Mate: Another way of sharing images!

Telestr8 Mate is a WinRT (Windows Runtime) Application designed primarily to share pictures from your Photos Application or any photos-sharing application you have.
Since Telestr8 Mate was also planned to be on Windows Store, there is a guide that comes along with the application. Also, when app is launched, there is a step-by-step instructions on how to go about using it.

Important!

Telestr8 Mate is the companion app of Telestr8 (a desktop application). Telestr8 will be discussed on a blog post following this, but it is important to know that in order for Telestr8 Mate to function properly, you will need to download and install Telestr8 App, as well.

Here are the features of Telestr8 Mate:

Settings

When app is launched, Telestr8 Mate provides a screen with instructions on how to connect to an IP Address where Telestr8 (A desktop application that I will discuss following this blog) is installed.

Telestr8 Mate: how to connect

Screen for connecting using Telestr8 Mate

Steps in connecting:

a) Find out what IP Address Telestr8 is connected to by running the program and clicking on the settings button (computer icon).
b) Go back to Telestr8 Mate, select the settings charm, go to service settings and put IP Address on the text box or select any discovered device that pops up below the validate button.
IP address
c) Validate!

Sharing

Once Telestr8 Mate changed screen to “YOU ARE CONNECTED”, congratulations you are now ready to share your images to Telestr8.

telestr8_mate_sharescreen

Instructions on how to share using telestr8 mate

Steps in sharing images using Telestr8 Mate

a) Find the image you want to share on your Photos Application.
b) Click on Share charm and select Telestr8 Mate.
c) Share!
d) You should be able to see the picture you shared on whatever device you installed Telestr8 in. The picture will appear at the top-right corner of Telestr8 app.

Lessons Learned

  • As a developer, being able to work with WinRT application is a big deal. I had the chance to struggle figuring out Application Lifecycle: OnSuspended, OnResuming, OnLaunched and just about how will my breakpoints on OnResuming event will be hit.
  • I learned how WinRT works by reading other’s blogs, thorough researching and just TRYING IT OUT MYSELF.
  • Lastly, just a shout-out that following this post is Telestr8 App, so keep reading!

WinRT Framework: Application State

From the previous blog entry, on our diary application, we used the framework to help us navigate from the MainPage to the Diary Page and vice versa.
On the Diary Page, we will notice that if we write some text on the textbox, when we navigate away from that page and go back to the diary page, the text is not persisted. This means that the text is not stored. So navigating away from the page, we lose that text.

How do we fix this? Simple! The framework has its way! So, let’s get to coding mode.

1) Let’s edit the DiaryPageVM.cs and add a text property to bind to our textbox.
We also need a Bindable class (part of the framework) to have a way for us not be notified when the property is updated.
In the Bindable class, the NotifyPropertyChanged method fires the INotifyPropertyChanged.PropertyChanged event for the Property that you pass in.
Luckily, the framework already has a class we can inherit that takes care of this; instead of us making another helper class.

  public class DiaryVM : Bindable, IRequireNavigationService
    {
        public INavigationService NavigationService { set; get; }

        private string _diaryText;
        public string DiaryText
        {
            get { return _diaryText; }
            set
            {
                _diaryText = value;
                NotifyPropertyChanged(() => DiaryText);
            }
        }
    }

2) Now that we have a text property to bind to the textbox, we need the framework to persist the state of our application.
On the same page (DiaryPageVM.cs) we need an interface — ISupportTransientState

public class DiaryVM : Bindable, IRequireNavigationService, ISupportTransientState
  • This interface tells the framework that our ViewModel has a transient state.
  • The framework then is responsible for persisting and restoring the state.

3) Add a TransientState class that will have the properties that we need its state to be persisted — Text!

[DataContract]
public class TransientState
        {
            [DataMember]
            public string Text { get; set; }
        }
  • The DataContract and DataMember are both used for serialization. That means, the data is being stored and its value can be access in the same or different computer environment.

4) Implement the methods of the ISupportTransientState.
4a) GetTransientStateTypes() that returns all the TransientState that we need.

public IEnumerable GetTransientStateTypes()
        {
            yield return typeof(TransientState);
        }

4b) GetTransientState() that sets the value of the TransientState’s Text property to the DiaryText and creates an instance of the TransientState class.

public object GetTransientState()
        {
            return new TransientState { Text = DiaryText };
        }

4c) UpdateTransientState() that updates the value of the Text property when DiaryText gets updated.

public void UpdateTransientState(object untypedState)
        {
            TransientState state = (TransientState)untypedState;
            DiaryText = state.Text;
        }

5) Bind the DiaryText to the textbox in DiaryPage.xaml

        <TextBox Grid.Row="1"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch" Margin="100"
                 AcceptsReturn="True"
                 Text="{Binding DiaryText, Mode=TwoWay}"/>

And we are done! Now let’s run the program and make sure it works.
THINGS TO REMEMBER:

  • When we navigate to the DiaryPage and put some text on the textbox, and we navigate away from that page, the text gets persisted and clicking the ‘ForwardButton’ restores the state of the text.
  • Now the question is why not click the Go to Diary button (center) of the MainPage? On my previous blog entry about Navigation, I talked about when we click the Go to Diary button, we are creating a new instance of the DiaryPage. When we click that instead of the forward button, the text will not be there.
  • If we try to use the navigation arrows at the top of our application, we are keeping the same instance of the DiaryPage, which means we will see that the text is persisted

For reference, Here is a link to the solution

WinRT Framework: Navigation

On the WinRT Framework: Getting Started blog, we got everyone setup on referencing the Framework to our project.
Now we are ready to move on to Navigation.

Overview: For this example, we will make a Diary App that has a Main Page and Diary Page.
The Navigation between the Main page and Diary page will be a “Go Forward” and “Back” button.

1) Let us first create DiaryPageVM.cs (class) and a DiaryPage.xaml (page)

2) On MainPageVM.cs, we need a DelegateCommand to navigate to the diary page.

  • DelegateCommand works like a ‘Click’ property of a button, but unlike ‘Click’, DelegateCommand is used in the ViewModel and not on the code-behind.
  • This points out the idea of MVVM pattern that the view is decoupled from the viewmodel.
  • The implementation of IRequireNavigationService tells the framework that our ViewModel would like to get access to the Framework’s NavigationService in order to be able to navigate to other pages
  • This interface has a NavigationService property that has a Navigate method that we can use to tell framework which view model we want to navigate to.
  • In this case, we want to navigate to DiaryPageVM, so we can simply say NavigationService.Navigate<DiaryPageVM>();
public class MainPageVM : IRequireNavigationService
	{
		public DelegateCommand NavigateToDiaryCommand
		{
			get
			{
				return new DelegateCommand(() => NavigationService.Navigate());
			}
		}

		public INavigationService NavigationService { get; set; }
	}

3) On MainPage.xaml, we add the buttons to navigate to the Diary page
One button (in the middle) to instantiate a new instance of a diary page to navigate to.
The other button (at the top-left) to navigate to the same instance of the diary page that was already created.

 <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>

        <Button HorizontalAlignment="Left"
                Command="{Binding NavigationService.GoForwardCommand}"
                Style="{StaticResource BackButtonStyle}">
            <Button.RenderTransform>
                <RotateTransform Angle="180"
                                 CenterX="30"
                                 CenterY="26" />
            </Button.RenderTransform>
        </Button>
        
        <StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button Content="Go to Diary"
                    Command="{Binding NavigateToDiaryCommand}"></Button>
        </StackPanel>
    </Grid>
  • The NavigationService already has a property GoForwardCommand that we can access for the navigation.
  • The NavigationToDiaryCommand is the DelegateCommand that we just created on the viewmodel.

4) On DiaryPageVM.cs, we need a way to navigate away from the diary page back to the main page.
This means that we need to implement the IRequireNavigationService on the MainPageVM, so we can access the NavigationService property.

public class DiaryVM : IRequireNavigationService
	{
	    public INavigationService NavigationService { set; get; }
	}

5) On DiaryPage.xaml, we need to add the button to navigate back to the main page and a textbox to put our diary entry.

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>

        <Button HorizontalAlignment="Left"
                Command="{Binding NavigationService.GoBackCommand}"
                Style="{StaticResource BackButtonStyle}">
        </Button>

        <TextBox Grid.Row="1"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch" Margin="100"
                 AcceptsReturn="True"/>
    </Grid>

When we run the program, we notice that on the Main Page, there is only one button (center). The reason is there is no instance of diary page yet.
When we click the ‘Go to Diary’ button, it creates the diary page instance, so when we navigate back to the main page, we can see the ‘forward’ button.

Congratulations! You built an app that can be navigated from one page to another.
Here is the link to the whole solution

WinRT Framework: Getting Started

Windows Runtime (WinRT) is used to make Windows store applications. The problem is that the WinRT API is designed in a way that Views and ViewModels are tightly coupled. This means that all the business logic, events like button click, are in “code-behind” of the view instead of it being in the view model. This Framework allows us to enforce a solid MVVM pattern that puts all the business logic in the view model making it decoupled from the view.

Before we make use of the functionalities of the framework, we need to make sure that it is referenced correctly in our project.
To read an in-depth explanation about the framework, refer to this: Introduction of WinRT Framework

1) In Visual Studio, create a new Blank App project
BlankApp

2) Add a reference to the framework
Framework Reference

3) We need to change the base class of the app-class to DefaultApplication. By doing this, the DefaultApplication takes care of the initialization of the framework. This means that the framework will automatically be set up for us. To do this, we need to change <application> tag to <mvvm:DefaultApplication> and we also need to add a namespace: xmlns:mvvm=”using:WinRTFramework.DefaultImplementations”

<mvvm:DefaultApplication x:Class="DemoProject.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mvvm="using:WinRTFramework.DefaultImplementations">

4) Since we changed the base class to DefaultApplication on the xaml, we need to do the same thing in the code behind (App.xaml.cs)
We need the App to inherit from DefaultApplication.

sealed partial class App : DefaultApplication

5) Now, we need to add a new class called MainPageVM.cs. This will become the view model of our MainPage View.

MainPageVM_class

6) Then we implement methods of DefaultApplication:
6a) IsSearchSupported tells the Framework if we support search or not..
For this instance, we will not be doing search so we can just set the value to ‘false’. Down the road, if we want to make an application that supports searching, we can just change the value to return ‘true’

protected override bool IsSearchSupported
	    {
	        get { return false; }
	    }

6b) Next we need to provide the framework with an adapter to our IoC Container, which will allow the framework to create instances from our ViewModels Types. If you use your own IoC Container (such as Autofac or Prism), you should develop an IoCAdapter by implementing the IoCAdapter Interface. If, however, your project does not use an IoC Container, you can use the framework’s DefaultIoCAdapter, which is a very simplistic IoC Container implementation that uses types’ default constructors to create their instances.

protected override IIoCAdapter IoCAdapter
	    {
		  get { return new DefaultIoCAdapter(_viewToVMMap.Values); }
	    }

6c) The framework uses an instance of a IViewViewModelMapper to find out which View belongs to which ViewModel and vice versa. If you follow a fixed naming pattern in your project (such as the ViewModel for Page XYZPage is always called XYZViewModel), you would develop an IViewViewModelMapper which finds matching partners according to this naming rule. If you, however, don’t have such a naming rule, you can use the Framework’s DefaultViewViewModelMapper which accepts an instance of a Dictionary that simply maps the type of a View to the type of a ViewModel

Dictionary _viewToVMMap = new Dictionary();
 public App()
        {
			_viewToVMMap.Add(typeof(MainPage), typeof(MainPageVM));
        }

protected override IViewViewModelMapper ViewViewModelMapper
	    {
		    get { return new DefaultViewViewModelMapper(_viewToVMMap, IoCAdapter); }
	    }

6d) Lastly, we want to tell the framework what page we want to navigate to. We achieve this by specifying in the Navigate() method what ViewModel of the page that we want to navigate to.
This means that if we want to navigate to the MainPage View, we need to specify its view-model to the Navigate method like this — Navigate<MainPageVM>().

	    protected override bool NavigateToInitialPage(INavigationService navigationService)
	    {
		    return navigationService.Navigate();
	    }

Here is the link to the solution