0% found this document useful (0 votes)
34 views62 pages

DNCMag Issue21

Uploaded by

hopesend
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views62 pages

DNCMag Issue21

Uploaded by

hopesend
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

TABLE OF CONTENTS

Upgrading Existing
06 C# Code to C# 6.0

Creating Graphics Using SVG


14 and AngularJS

Run Desktop applications in the


20 Cloud using Azure Remote Apps

Using AngularJS with Bower and


34 RequireJS in Visual Studio

Create Your First Diagnostic


40 Analyzer in Visual Studio 2015

Angular 2 Developer Preview


58

Universal Windows 10 Platform


47 (UWP) Music App for
Windows Phone & Raspberry Pi2
EDITORIAL
Welcome to the 21st Edition of the DNC Magazine. This edition warms up with
an excellent article by Damir on C# 6.0 where he categorizes some new C#
features and shows us an upgrade path from previous versions of C# to the new
one. For our client-side devs, we have three awesome articles by Gil, Mahesh and
Ravi on AngularJS; mashing it up it with SVG, Require.js and Bower.

So far, we have been running Web apps in the Cloud. Kunal in his article shows
us why and how to use Azure to run Desktop apps in the Cloud. Shoban follows
up on his Windows 10 UWP series and deploys the same code base to Windows
Mobile and Raspberry Pi. Damir follows up on his Visual Studio 2015 Diagnostic
Analyzer article, by showing us how to actually create one for our needs.
Suprotim Agarwal Enjoy this edition and here's everybody in the DNC Team wishing you a very
Happy Diwali and a joyous Holiday Season! We'll see you again in the New Year!
Editor in Chief

CREDITS
Editor In Chief Copyright @A2Z Knowledge Visuals.
Suprotim Agarwal Reproductions in whole or part prohibited
[email protected] except by written
permission. Email requests to
Art Director “[email protected]
Minal Agarwal
[email protected] Legal Disclaimer:
The information in this magazine has been
Contributing Authors reviewed for accuracy at the time of its
Damir Arh publication, however the information is distributed
Gil Fink without any warranty expressed or implied.
Kunal Chandratre
Mahesh Sabnis www.dotnetcurry.com/magazine
Ravi Kiran
Shoban Kumar

Technical Reviewers
Gil Fink
Ravi Kiran
Suprotim Agarwal POWERED BY

Next Edition
4th Jan 2016

Windows, Visual Studio, ASP.NET, Azure, TFS & other Microsoft products & technologies are trademarks of the Microsoft group of companies. ‘DNC Magazine’ is an independent
publication and is not affiliated with, nor has it been authorized, sponsored, or otherwise approved by Microsoft Corporation. Microsoft is a registered trademark of Microsoft
corporation in the United States and/or other countries.
Upgrading
Existing
C# Code to

C# 6.0
We are already used to the fact that a new version of Visual Studio also includes a new version of C#.
Visual Studio 2015 is no exception to this: its new C# compiler supports version 6 of the language. Unlike
previous language updates, this version is not focused on a single major feature. Instead, it includes
several smaller improvements that did not make it into previous releases. Most of these features make the
language more concise and less error prone.

However, does it make sense to change your existing C# code base to take advantage of the new C# 6.0
features? Let us find out.

6 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


What Has Changed in When you rename the parameter, you will need to
remember to change the string literal as well – the
C# 6.0? compiler will not warn you about it.

Changes in C# 6.0 make the language less verbose. The nameof operator in C# 6.0 is a perfect solution
Most of them affect declarations of class members to this problem: nameof(n) call will compile into
and building of expressions. The only exceptions are a string literal while keeping strong typing at the
improvements to try-catch-finally statements source code level:
and the introduction of using static clause. Filip
Ekberg already wrote an article about them when public int GetFibonacciNumber(int n)
Visual Studio 2015 was still in preview, but a lot has {
changed between then and the final release. Instead if (n < 0)
of just writing an updated article on new language {
throw new
features, I will rather focus on the benefits that they
ArgumentException("Negative value
can bring to the code base, when used appropriately. not allowed", nameof(n));
}

Best Features of C# 6.0 // TODO: calculate Fibonacci number


return n;
I will start out with new features, which you should }
start using in your code base immediately, wherever
applicable, because they can have a positive impact Not only will the compiler now warn you if you
on the code maintainability and readability. Some forget to rename the parameter usage in nameof
of these new features are: nameof operator, null- operator, rename refactoring in Visual Studio will
conditional operator, and support for await in automatically rename it for you.
catch and finally blocks. I would strongly suggest
you apply them even to your existing code once you Null-conditional Operator
have switched to Visual Studio 2015.
Whenever you want to invoke a property or a
Nameof Operator method on a class, you need to check that the
instance is not null beforehand, otherwise the
Base class libraries sometimes require you dreaded NullReferenceException will be thrown
to put symbol names (such as property at run time. This can result in a lot of trivial code
and parameter names) as string literals in that exists only to check for values not being null:
your code, e.g. when your class implements public int GetStringLength(string arg)
INotifyPropertyChanged interface or when {
throwing an ArgumentException: return arg != null ? arg.Length : 0;
}

public int GetFibonacciNumber(int n) Null-conditional operator in C# 6.0 can replace all


{
if (n < 0) such null checking code:
{
throw new public int GetStringLength(string arg)
ArgumentException("Negative qvalue {
not allowed", "n"); return arg?.Length ?? 0;
} }

// TODO: calculate Fibonacci number The arg?.Length in the above code will return
return n; arg.Length when arg is not null; otherwise,
it will return null. You can even cascade
}

www.dotnetcurry.com/magazine 7
multiple calls one after another: arg?.Length?. Support for Await in Catch and
ToString() will return null if arg or arg.Length are
Finally Blocks
null and will never throw an exception.

The async and await keywords, introduced in


Null-conditional operator is not limited to
properties and methods. It also works with C# 5.0, made asynchronous programming much
delegates, but instead of invoking the delegate easier. Instead of creating a callback for each
directly, you will need to call its Invoke method: asynchronous method call, all the code could now
be in a single async method, with the compiler
public event PropertyChangedEventHandler creating the necessary plumbing instead of the
PropertyChanged; developer. Unfortunately, await keyword was
not supported in catch and finally blocks.
private void This brought additional complexity to calling
NotifyPropertyChanged(string asynchronous methods from error handling blocks
propertyName) when they were also required to complete before
{ continuing. Here's an example:
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs
public async Task
(propertyName)); HandleAsync(AsyncResource resource, bool
} throwException)
{
Implementing events this way also ensures Exception exceptionToLog = null;
that they are thread-safe, unlike their naïve try
implementation in previous versions of C#, as {
shown here: await resource.
OpenAsync(throwException);
public event PropertyChangedEventHandler }
PropertyChanged; catch (Exception exception)
{
private void exceptionToLog = exception;
NotifyPropertyChanged(string }
propertyName) if (exceptionToLog != null)
{ {
if (PropertyChanged != null) await resource.
{ LogAsync(exceptionToLog);
PropertyChanged(this, new }
PropertyChangedEventArgs }
(propertyName));
} Of course, if you wanted to rethrow the exception
} and keep the stack trace, it would get even more
complicated.
In multithreaded scenarios, the above code could
throw a NullReferenceException, if another With C# 6.0, none of this is required any more –
thread removed the last remaining event handler; async methods can simply be awaited inside both
after the first thread checked the event for being catch and finally blocks:
null, but before it called the delegate. To avoid this,
PropertyChanged needed to be stored into a local public async Task
HandleAsync(AsyncResource resource, bool
variable in previous versions of C#, before checking throwException)
it for null. {
try
The null-conditional operator in C# 6.0 takes care of {
this automatically. await resource.
OpenAsync(throwException);

8 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


} • You can directly use variable names and
catch (Exception exception) expressions in placeholders, instead of numerical
{ values. They will be checked at compile time.
await resource.LogAsync(exception);
}
finally • Additional formatting strings can still be included
{ in the placeholder after the colon, similar to
await resource.CloseAsync(); String.Format.
}
}
Nevertheless, string interpolation is not a universal
replacement for String.Format, e.g. you will
The compiler will do all the necessary plumbing
still need to use String.Format for all localized
itself, and you can be sure that it will work correctly.
strings and the translators will still have to deal
with numeric placeholders.
Recommended C#
6.0 Features for New Improvements to Member
Declarations
Projects
You can take advantage of several new language
Some additional new features in C # 6.0 can constructs in your member declarations:
simplify writing new code, but do not add enough
benefits to justify modifying existing code. All of • Auto-properties can now be initialized the same
them are just syntactic sugar, which will save you way as fields:
some typing, but will not make much difference
otherwise. public string FullName { get; set; } =
"Damir Arh";

String Interpolation • Read-only auto-properties are now supported


as well. They create a readonly backing field.
If C# is not the only programming language you Their value can only be set with an auto-property
work with, you might be familiar with this language initializer or inside the constructor:
construct called "String Interpolation" from other
languages such as PowerShell, TypeScript, Python, public string FullName { get; } = "Damir
etc. In most cases, you can use it instead of String. Arh";
Format calls, making them easier to read and safer
to use. Here is a simple example in C# 6.0: • Simple methods and read-only properties
can have their body defined with a lambda-like
var formattedPrice = $"{price:0.00} €"; expression:

It is equivalent to the following String.Format call: public int Add(int a, int b) => a + b;
public string FullName => _name + " " +
_surname;
var formattedPrice = String.
Format("{0:0.00} €", price);
Exception filters
Notice the following key aspects:
The final feature in this category is new only in
• Literals for string interpolation must start C# 6.0; both Visual Basic and F# have already
with $ character. This makes them of type supported it in previous versions. It can be used to
FormattableString. filter the exception caught by a specific catch block
not only by its type but by using any exception
property:

www.dotnetcurry.com/magazine 9
try
{ Remaining C# 6.0
}
// ... Features
catch (ArgumentException exception) when
(exception.ParamName == "ignore") There are a couple of new language features in
{ } C# 6.0, which I have not mentioned yet. To be
honest, in most cases I don’t recommend using
Before exception filters were available in C# 6.0, them, because although they can make the code
you could write the same code in previous versions less verbose, they can also make it more difficult
of C# in the following manner: to understand, especially in larger teams and in
projects with longer time span.

try
{ For the sake of completeness, I am nevertheless
// ... listing them here:
}
catch (ArgumentException exception) - Using static clause can be used to import static
{ class members into scope, so that they do not need
if (exception.ParamName != "ignore")
{ to be prefixed with the class name any more. With
throw; the exception of a few well-known static classes,
} such as Math and Console, this can make it difficult
} to know where the methods in the code come from.
In the following example both System.Console
As you can see in the first example, the code using and System.Math are statically imported, which
exception filters is easier to understand, and it makes WriteLine and Pow methods directly
keeps the stack untouched when the filter condition available inside the scope:
is not matched. Although catching and re-throwing
the exception in the second example preserves
the stack trace inside the exception, the top frame using static System.Console;
on the CLR stack will point to the place it was using static System.Math;
rethrown, instead to where it was originally thrown. class Program
This can make an important difference in the {
information available when analysing a crash dump static void Main() {
resulting from such an exception. WriteLine(Pow(10, 2));
}
}
The Exception filter feature can also be abused for
unobtrusive logging:
- Index initializers expand on collection initializers
try and allow initialization of indexed values within a
{ single expression. They can be used with any type
// ... having an indexer, but for most types, the same
} can be achieved using collection initializers. In
catch (Exception exception) when the example below, index initializers are used to
(Log(exception)) initialize a dictionary:
{ }

This way the Log method can log all the exception var properties = new Dictionary<string,
string>
details without affecting the CLR stack. Of course, it {
must return false to prevent the catch block from ["Name"] = "Damir",
executing. ["Surname"] = "Arh",
["Country"] = "Slovenia"
};

10 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


- Collection initializers are not limited to calling
instance methods named Add anymore. Now
extension methods with the same name can be
called as well. The following example will work as
long as there is an extension method named Add
accepting a single parameter (Dictionary class
Figure 1: Visual Studio diagnostic analyzer in action
does not have such a method). For a developer
unaware of such an extension method, the
initializer can be completely incomprehensible: Unfortunately, there are no such code fixes built
into Visual Studio. To my knowledge, even in the
third party space, there is only a single code fix
var typeNames = new Dictionary<Type,
available that applies one of suggested refactorings
string>
{ explained in this article: “Use ‘nameof(n)’ expression
typeof(string) instead.”, distributed as a part of Refactoring
}; Essentials Visual Studio extension at
http://bit.ly/1HkOtnt .
Before using any of the language constructs in this
section, consider the following: This does not mean that you are on your own
though. The renowned Visual Studio extension
• Does this construct really make the code better? ReSharper by JetBrains has been updated for Visual
• Is there no better way to achieve the same result? Studio 2015 and C# 6.0 and in its latest release
(9.2 at the time of writing), it includes so called
inspections for many of the new language features.
How Can Visual Studio
Help? • nameof operator,
• null-conditional operator,
Compared to the previous releases, static code • string interpolation,
analysis tools are vastly improved in Visual Studio • read-only auto-properties, and
2015. It introduces unified framework diagnostic • expression-bodied properties.
analyzers, which are presented to the user the
same way, whether they are built into Visual Studio The suggested fixes are also displayed as warnings
or provided by third party extensions or NuGet and can by default be applied via the lightbulb icon
packages. or by pressing Alt + Enter. There is no preview of the
changes though.
Code fixes are a part of this framework and could
prove useful in refactoring existing code to take
advantage of new features in C# 6.0. The ones that
are enabled for the project appear as information,
warnings or errors in the code (depending on the
configuration). Figure 2: Applying ReSharper quick-fixes

When activated in the editor window by clicking Most of the fixes can be applied at the document,
on the lightbulb icon or by pressing Ctrl + . ,the fix project or solution scope with a single action, as
(i.e. the refactoring) can be applied only to a single well. For those that can’t be applied, invoking code
occurrence, or to all occurrences in a document inspection for the whole solution will create a list
project or complete solution. This means that with of all issues found, which can be used for navigating
an appropriate code fix, a specific new language to them in code and fixing them one by one. It
feature could be applied to the whole solution in is still much quicker and reliable than doing it
one single action. completely by hand.

www.dotnetcurry.com/magazine 11
Figure 3: ReSharper code inspection results for solution

Unlike Refactoring Essentials, ReSharper is not a


free extension and you will need to pay for it if
you want to use it beyond the 30-day trial period.
It does offer a lot more than just the refactorings,
mentioned here though.

Conclusion:

C# 6.0 brings many small improvements to the


language. The categorization of these into three
different categories in this article is based solely
on my opinion and experience. As such, it is very
subjective and your opinion on individual new
features may vary. Nevertheless, if all of your team
members are using Visual Studio 2015 (which is
a prerequisite for using C# 6.0 language features),
I strongly suggest, you take a closer look at what
is new and decide for yourself which features you
want to use, and which not. Of course, I would be
very glad if you base your final decision at least
partly on my opinions expressed in this article

About the Author


Damir Arh has many years
of experience with Microsoft
development tools; both in complex
enterprise software projects and
modern cross-platform mobile
applications. In his drive towards
better development processes,
he is a proponent of test driven
development, continuous integration
and continuous deployment. He
shares his knowledge by speaking at
damir arh local user groups and conferences,
blogging, and answering questions
on Stack Overflow. He is an awarded
Microsoft MVP for .NET since 2012.

12 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Introduction

A couple of months ago I


started working with a startup
called Genome Compiler that
specializes in software platform
to accelerate Genome and DNA CREATING GRAPHICS
design. Their main product was
created using Flash and they
wanted me to help them to
create a new Genome viewer
USING
SVG AND
using plain web technologies.
They wanted to visualize
plasmids, which are small
DNA molecules represented
as a circle with annotations.

ANGULARJS
They also wanted to visualize
sequences, which are the
primary structure of a biological
molecule written in A, T, G and
C characters. To create such
visualization we needed the
ability to create graphics inside
the browser.

For more than four months I’ve


been helping Genome Compiler
Disclaimer: This article assumes that you have basic knowledge of
to create their viewer using both
AngularJS. If you are not familiar with AngularJS, I encourage you to stop
Scalable Vector Graphics (SVG)
reading and start learning about this framework today.
and AngularJS. During the time,
I learned how to combine SVG
and AngularJS together to create Editorial Note: You can learn more about AngularJS using our tutorials
biological models and other at http://www.dotnetcurry.com/tutorials/angularjs
graphics.
SVG in a Nutshell
In this article I’ll explore what
SVG is. Then, I’ll explain how SVG is an XML-based graphics model that you can use in your
SVG can be used in AngularJS front-end. As opposed to other new HTML5 graphics models
applications. Towards the end of (such as canvas and WebGL), SVG version 1.0 was made a W3C
the article, you will see a simple recommendation in 2001. The SVG developers’ adoption was very
application that combines both small due to the popularity of plugins such as Flash, Java and
SVG and AngularJS. Silverlight, and the lack of browser support. In 2011, W3C introduced
the second edition of SVG, version 1.1, and SVG gained a lot of
Note: The article won’t cover the attention as an alternative graphics model, besides the Canvas pixel
project that I’m doing for Genome graphics model.
Compiler due to the fact that
it’s too huge to be covered in an SVG is all about vector graphics. With SVG you can create and draw
article (or even in a book). two-dimensional vector graphics using HTML elements. These HTML
elements are specific to SVG, but they are part of the shapes appearance. For example, the following code
Document Object Model (DOM) and can be hosted snippet shows how to create two rectangles with
in web pages. The vector graphics can be scaled different colors using the RECT element:
without loss of image quality. This means that the
<svg width="400" height="200"
graphics will look the same in different screens and version="1.1" xmlns=
resolutions. This makes SVG a very good candidate "http://www.w3.org/2000/svg">
to develop graphics for applications that can be <rect fill="red" x="20" y="20"
run on different screens (mobile, tablets, desktop or width="100" height="75" />
even wide screens). Some prominent areas where <rect fill="blue" x="50" y="50"
Vector graphics are used are in CAD programs, width="100" height="75" />
</svg>
designing animations and presentations, designing
graphics that are printed on high-res printers and so
The output of running this piece of SVG will be as
on.
shown here:

The fact that SVG elements are HTML elements


makes SVG a very interesting graphics model.
You can get full support for DOM access on SVG
elements. You can use scripts, CSS style and other
web tools to shape your graphics and manipulate it.
As opposed to Canvas, which doesn’t include state,
SVG is part of the DOM and therefore you have the
elements and their state for your own usage. This
makes SVG a very powerful model. There is one
notable caveat though – drawing a lot of shapes can
result in performance decrease.

When you use SVG, you define the graphics within


your HTML using the SVG tag. For example, the Figure 1: Two rectangles drawn by SVG
following code snippet declares an SVG element:
Here are a couple of points to note in the snippet:
<svg version="1.1" xmlns="http://www.
w3.org/2000/svg"> 1. The last rectangle will appear on top of the first
</svg> rectangle. SVG behavior is to put the last declared
elements on top of previously declared elements, if
It is an HTML element and can be embedded inside there are shapes that overlap.
your web page as any other HTML element. If not
stated, the width of the SVG element will be 300 2. In order to create a rectangle, you have to
pixels and its height 150 pixels. indicate its left-top point using the x and y
attributes and its width and height. The default
Note: Pay attention to the SVG XML namespace values for these attributes are all set to 0 and if you
which is different from regular HTML. We will use don’t set them, the rectangle will not be drawn on
this information later on when we will use SVG with the SVG surface.
AngularJS.
There are other shapes that you can use such as
Using Shapes circles, ellipsis, polygons, polylines, lines, paths, text
and more. It is up to you to learn to draw these
SVG includes a lot of built-in shape elements that shapes and a good reference for the same can be
can be embedded inside the SVG tag. Each shape found in the Mozilla Developer Network (MDN) -
has its own set of attributes that helps to create the https://developer.mozilla.org/en-US/docs/Web/SVG/
Tutorial/Basic_Shapes.

www.dotnetcurry.com/magazine 15
Other than attributes, shapes can also include w3.org/2000/svg">
styling using style attributes such as stroke or fill. <defs>
Stroke accepts a color to create the shape border <linearGradient id="lg1">
and Fill accepts a color to fill the entire shape. You <stop offset="40%"
stop-color="yellow"/>
can also set styles using regular CSS but not all <stop offset="60%" stop-color="green"
CSS styles can be applied on SVG elements. For />
example, styles such as display or visibility can be <stop offset="80%" stop-color="blue"
used with SVG elements but margin or padding has />
no meaning in SVG. The following example shows a </linearGradient>
rectangle with some inline styles: </defs>
<rect fill="url(#lg1)" x="50" y="50"
<rect x="200" y="100" width="600" width="100" height="100"/>
height="300" style="fill: yellow; stroke: </svg>
blue; stroke-width: 2"/>
..and the output of running this SVG will be:
As you can see in the code snippet, the rectangle
will be filled with yellow color, will have a blue
border, with a border width of 2 pixels.

You can group shapes using the g element. The g


element is a container for other shapes. If you apply
style to a g element, that style will be applied to
all its child elements. When you create SVG, it is
very common to group some elements inside a g
Figure 2: Gradient inside a rectangle
container. For example the following snippet shows
you the same two rectangles from Figure 1 but
grouped inside a g element: A couple of things to notice about the snippet:

<svg width="400" height="200"


version="1.1" xmlns="http://www. 1. I defined the gradient using the linearGradient
w3.org/2000/svg"> element. There are other elements that you can use
<g> to define other graphical aspects. Each element has
<rect fill="red" x="20" y="20" its own attributes and sub elements, so it’s up to
width="100" height="75" /> you to learn them.
<rect fill="blue" x="50" y="50"
width="100" height="75" />
</g> 2. The gradient has an id which is later on used in
</svg> the rectangle using the url(#nameOfSVGElement)
syntax.
Using SVG Definitions
Note: The article doesn’t cover all the possible SVG
SVG includes a defs element which can be used element definitions.
to define special graphical SVG elements such as
gradients, filters or patterns. When you want to use Now that we are familiar with SVG it is time to
a special SVG element, you first define it inside the move on and see how SVG and AngularJS work
defs element and later on, you can use it in your together.
SVG. Make sure you specify an id for your special
element, so that you can use it later. SVG + AngularJS =

The next snippet shows how to define a linear You can combine SVG and AngularJS and it is very
gradient: straight forward. Since SVG elements are part of the
DOM, you can add them into view templates both as
<svg version="1.1" xmlns="http://www. static graphics, and also as dynamic graphics. The

16 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


first option is very simple and you just embed static Now that we know how to combine SVG and
SVG inside the HTML. The second option has a few AngularJS, it is time to see some code in action.
caveats that you need to know in order to be on the
safer side. Building a Simple App with SVG and
AngularJS
The first caveat is dynamic attributes and data
binding. Since SVG has its own XML definition, it The application that we are going to build will
doesn’t understand AngularJS expressions. That generate a rectangle and you will be able to change
means that if you will try to use SVG attributes with its width and height, using data binding:
data binding expressions (curly brackets), you will
get an error. The work around is to prefix all the
dynamic attributes with ng-attr- and then set the
binding expression. You can find a reference about
ng-attr- prefix in the AngularJS website under the
topic “ngAttr attribute bindings” using the following
link: https://docs.angularjs.org/guide/directive .The
following example shows you how to use the ng-
attr and define databinding expressions:

<rect ng-attr-x="{{xAxis}}" ng-


attr-y="{{yAxis}}" ng-attr-
height="{{rectHeight}}" ng-attr-
width="{{rectWidth}}"></rect>

In the example, you can see that all the rectangle


attributes are set to some scope properties.

The second caveat is related to directives. Since


the SVG XML definitions are different from HTML,
Figure 3: Application using SVG and Angular
directives that generate SVG elements need to
declare that they generate SVG. That means that
in the Directive Definition Object (DDO) that you We will first start by defining a rectangle directive
return to define the directive, you will need to set that will resemble some of the code snippets that
the templateNamespace property to 'svg'. For you saw earlier:
example, the following snippet shows a simple
directive DDO that declares that it generates SVG:
(function () {
(function () { 'use strict';
'use strict'; angular.
angular. module("svgDemo").
module("svgDemo"). directive("ngRect", ngRect);
directive("ngRect", ngRect); ngRect.$inject = [];
ngRect.$inject = [];
function ngRect() { function ngRect() {
return { return {
restrict: 'E', restrict: 'E',
templateUrl: <rect x="50" y="50" replace: true,
width="100" height="100"></rect>', scope: {
templateNamespace: 'svg' xAxis: '=',
}; yAxis: '=',
} rectHeight: '=',
}()); rectWidth: '='
},
templateUrl: 'app/common/

www.dotnetcurry.com/magazine 17
templates/rectTemplate.html', }
templateNamespace: 'svg'
}; init();
} }
}()); }());

The directive will include an isolated scope that can In the controller, we define the properties that will
accept the x, y, width and height of the rectangle. It be used later for data binding. Now we can look at
also declares that it generates SVG and that it loads the template itself:
a template. Here is the template code:

<rect ng-attr-x="{{xAxis}}" ng- <div>


attr-y="{{yAxis}}" ng-attr- <div>
height="{{rectHeight}}" ng-attr- <svg height="300" width="300">
width="{{rectWidth}}"></rect> <ng-rect x-axis="demo.xAxis"
y-axis="demo.yAxis" rect-height="demo.
Now that we have our rectangle directive, we will rectHeight" rect-width="demo.
rectWidth"></ng-rect>
define a directive that will hold our entire demo: </svg>
</div>
(function () {
'use strict'; <div>
angular. <label>Set Rectangle Width:
module("svgDemo"). </label>
directive("ngDemo", ngSvgDemo); <input type="text"
ngSvgDemo.$inject = []; ng-model="demo.rectHeight" />
</br></br>
function ngSvgDemo() { <label>Set Rectangle Height:
return { </label>
restrict: 'E', <input type="text"
templateUrl: 'app/common/ ng-model="demo.rectWidth" />
templates/demoTemplate.html', </div>
controller: 'demoController', </div>
controllerAs: 'demo'
}; Please observe the usage of ng-rect directive that
}
}()); we have created, and the binding of its attributes to
the controller attributes. Also, we have bound the
textboxes to the relevant properties using ng-model
The main thing in the directive is the controller that
directive. That is all.
it will use, and the template that it will load. So let’s
see both of them. We will start with the controller:
Now we can create the main web page and the
(function () { svgDemo module. Here is how the main web page
'use strict'; will look like:
angular.
module("svgDemo"). <!DOCTYPE html>
controller("demoController", <html lang="en">
demoController); <head>
demoController.$inject = []; <meta charset="UTF-8">
<title>SVG & Angular</title>
function demoController() { <link href="styles/main.css"
var demo = this; rel="stylesheet"/>
function init() { </head>
demo.xAxis = 0; <body>
demo.yAxis = 0; <div ng-app="svgDemo">
demo.rectHeight = 50; <section class="body-content">
demo.rectWidth = 50; <ng-demo></ng-demo>

18 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


</section> About the Author
</div>
<script src="app/vendor/angular/ Gil Fink is a web development expert,
angular.min.js"></script> ASP.NET/IIS Microsoft MVP and the
<script src="app/app.js"></script> founder of sparXys. He is currently
<script src="app/common/controllers/ consulting for various enterprises
demoController.js"></script> and companies, where he helps to
<script src="app/common/directives/ develop web and RIA-based solutions.
ngDemoDirective.js"></script> He conducts lectures and workshops
<script src="app/common/directives/ for individuals and enterprises who
ngRectDirective.js"></script> want to specialize in infrastructure
</body> and web development. He is also
</html> co-author of several Microsoft Official
gil fink Courses (MOCs) and training kits, co-
And here is how the svgDemo module will be author of "Pro Single Page Application
defined: Development" book (Apress), the
founder of Front-End.IL Meetup and co-
organizer of GDG Rashlatz Meetup. You
(function () { can get more information about Gil in
var app = angular.module('svgDemo', his website http://www.gilfink.net.
[]);
}());

This is a very simple application but it shows you


how to combine both SVG and AngularJS and to
create dynamic graphics in your applications. You
can also use common SVG generator libraries such
as Raphael or d3.js inside your directives but the
idea was to show you how to do raw SVG graphics
before you jump into a library.

Summary

SVG is a very powerful graphics model that can be


used in the browser. It generates graphics that looks
good and scales well across different screens and
resolutions. It also includes variety of elements that
can help you shape your graphics easier. As you
saw in the article, combining SVG and AngularJS to
generate some sophisticated graphics is not so hard.

As I wrote in the introduction, I was able to


generate very interesting biological models using
SVG and AngularJS and this should encourage you
to try and create your own models

Download the entire source code from GitHub at


bit.ly/dncm21-svg-angular

www.dotnetcurry.com/magazine 19
DESKTOPS IN THE CLOUD
RUN DESKTOP APPLICATIONS
IN THE CLOUD USING
AZURE REMOTE APPS

Introduction Azure Remote Apps is a fantastic feature to make your corporate


desktop/ windows applications run in the Cloud, while ensuring
that corporate policies and compliances are adhered to. Using this
In this article we'll explore the feature, users can experience true Bring-Your-Own-Device (BYOD)
following important aspects of scenarios while using their corporate applications. This article
Azure Remote Apps – explores various possibilities of Azure Remote Apps feature and
demonstrates how to run a sample Windows application with SQL
1. Azure Remote Apps - Why? Azure DB as backend and using “cloud only collection” of Azure
2. Concept Remote apps, in Microsoft Azure.
3. Architecture of Remote Apps
deployment model
4. Demonstration
Why do I need to run desktop
Let’s get started! applications in the Cloud?
Applicable Let us start with a very important question – Why do I need to run
Technology desktop apps in the Cloud? To understand this, we will spend some
Stack time understanding the use case of this feature.

1. Valid Microsoft Azure


subscription. A Free trial is
available here. Corporate Scenario
2. Sample desktop application. To understand a corporate scenario, first let me take a few steps back
You can use the one I have into the initial days of cloud computing. What was the important
posted with source code that concept behind cloud computing evolution?
accompanies this article.
If you were an Application Development Company Case 2 – Device Portability
wanting to develop an internet application to solve
a specific business problem, then to save you from Today, the world is experiencing an explosion of
the hassles of infrastructure set up and let you devices. People want an application that can work
focus on your application, Cloud Computing came on Laptop, should be able to work on their tablet,
into existence. This is the basic essence of cloud smartphone, mobile, desktop and so on. Additionally
computing. In Microsoft Azure, we have various if an application can run on any device, users of the
features existing today that can take care of all application don’t necessarily have to be part of their
your infrastructure needs of hosting an internet corporate network and don’t have to be present
application. Some popular features are – in their company premises. Rather they should be
able to work remotely. However if an application
1. Cloud Services (Web and Worker Role) – PaaS is a legacy app, then it may not work on the
offering latest hardware/ software. Here device portability
of desktop application and mobility is another
2. Azure Apps Service (Web Apps and WebJobs) – challenge corporates face.
PaaS offering
Case 3 – Moving from Capex to Opex
3. Azure Virtual Machines – IaaS offering
Usually large organization take the help from
These offerings take care of web application vendors to perform many activities. Sometimes
hosting. So the problem of Enterprise level web these corporates hire people on contract for a short
applications is dealt with, but what about Enterprise duration to get their work done. In such cases,
level desktop applications? Let’s take an example to companies are not willing to spend on hardware
understand this a bit more. cost as this might be a temporary affair for them.
In other words, they don’t want to spend money on
Case 1 – Productivity and high sensitive data loss Capex (Capital Expenditure) but they want to move
to Opex (that is operational cost), so that they use
the resources when in need and free them when not
I have observed a very common scenario in my
required. In traditional model of desktop application
country India where data entry work is outsourced
environments, this flexibility is quite challenging. So
from various global companies. Let’s say a data
moving from Capex to Opex which is recommended
entry company in India is having a couple of
in today’s IT world is another important challenge
hundred workers performing data entry, related
corporates face.
to health care claims information. These workers
are allocated a desktop machine which has an
application developed using C# or WPF. Now Domestic Scenario
imagine if the hardware crashes for a desktop
machine, then that unfortunate employee has to
This section will help you understand the
go to Support IT team of his/her organization and
challenges individual desktop users may face to
report the problem. The IT team will then need to
cope up with changing technologies, hardware and
provide a new desktop machine. They will need to
software requirements.
configure the pre-requisites on the new desktop,
then install the actual application. In big companies,
this can take a couple of days, after which that Let’s say a user having a desktop PC is running
employee can start his/her work. Additionally if Windows 7 basic edition with 4GB of RAM and
there is any sensitive data on that machine, then 100GB of HDD. At a later date, he wishes to use
it needs to be restored. This problem arose at the modern software’s like Office 2016, Visual Studio
first place because a local desktop machine was 2015, or assuming he is game freak; he would like
being used for performing some sensitive work. In to run Call Of Duty latest version on his existing
this scenario, Productivity is affected and Loss of desktop machine. Now all this with 4GB RAM will
sensitive data is high. kill the machine if these software were to run on

www.dotnetcurry.com/magazine 21
it simultaneously. In fact some of the software’s anywhere
hardware prerequisites may not get full filled
because of the existing desktop configuration. So 5. User specific shared storage helps in avoiding
what is the solution? data loss

One solution is to increase the capacity of the Looking at these benefits, it is quite clear running
existing machine. In that case, he will have to desktop applications in Cloud environment is a
purchase 8GB or 16GB of RAM, a bigger capacity much better option.
HDD and so on. In essence, he will have to shell
out money from his pocket to make use of all the Azure Remote Apps is an offering from Microsoft
modern software’s. Now even if he does invest, Azure that makes it easy to run desktop applications
software gets outdated very soon. He may not need on the reliable platform of Azure.
to use Office 2016 every day and after clearing all
stages of the Call of duty game, he may want to get
rid of it. So the additional investment done on this
machine to run these modern software, will not The concept behind Azure
be recoverable in this scenario and it may not get
utilized to its fullest capacity. This is the problem. Remote Apps
Running desktop application on a remote machine
High Level Solution and accessing the app through a remote connection
is the basic concept behind Azure Remote Apps.
To overcome these challenges faced in corporate However this is not a new concept. This concept has
and domestic scenarios, companies like Microsoft been in practice since long and is commonly known
offering cloud computing for Enterprises came up as Remote Desktop Service on Windows. Basically
with the concept of Desktop as a Service (DaaS) anyone who is remoting from one computer to
commonly known as Desktop Virtualization. another computer using remote desktop connection
(.rdp file) client from Windows PC, is using RDS
So as a part of this concept, there is a desktop technology behind the scene.
application installed on user’s machine/ device.
The user logs in to that desktop application from A typical high level architecture of RDS is as shown
his machine / device. After successful login, all the here –
modern software & services would be available for
consumption. Although the services/ application
run on remote machine (cloud environment), they
will appear to the user as if they are running locally.
Once done, the user closes the application and he
would be charged only for what he has consumed.

This approach helps in –

1. Getting rid of hardware and software upgrades

2. Any modern device compatibility can be achieved


Session Host (RDSH) - The first component of
easily
RDS is session host. This is where the actual code
or application executes. You can run farms of
3. Applications scale without large capital expense
these session host servers and you can run same
application on multiple server machines.
4. Provide access to corporate applications from

22 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Connection Broker - When we use multiple session that brings in scalability, agility, resiliency, high
host server to host the same application, then user availability, global access and all cloud inherent
connections should be distributed across them. This benefits you can think of, to corporate applications.
is where connection broker helps. Its job is similar
to load balancer in Azure.
Remote Apps
RD Web Access - RD Web Access is a simple web Deployment Choices
portal that helps users to consume applications
from browsers. Azure Remote Apps support two types of
deployment.
Gateway - Helps you to make connection from
public internet to your private network of multiple
1. Cloud Only
session host servers and farm.
This is a very straight forward and easy deployment
option. Microsoft has planned to make software
License Server - Used for keeping a track of users
readily available through this option. This is also
using the application.
called as “Cloud Collection”. This collection resides
completely in Azure.
Creating RDS on Azure VM is out of scope for this
article. Once you have configured RDS in Azure VM,
Users can authenticate against cloud only collection
you can publish the application from that VM and
based apps using Azure AD or individual Microsoft
can access it using a web browser. A typical url of
Account. As of today, with this deployment choice,
RDS web access is as follows:
you get a trial version of Office 2013.
https://yourCloudServiceName.cloudapp.net/rdweb.

When you provision Remote Apps cloud only


If you access the url of RDWeb, the browser will
namespace with Office 2013 trial version, internally
display a published application from session host
Windows Server 2012 and RD session host gets
server as shown here –
configured for you. On these RD session host
machine, the business application which in current
case would be Office 2013 trial version, will get
configured automatically and published as well. So
internally they have prebuild image of Office 2013
trial version that gets configured on session host.

2. Hybrid
The red highlighted box displays the applications
that are running on Azure VM (a remote machine) Hybrid deployment is where your application can
and can be accessed from the local machine (th’e work in Azure environment as well as on-premises
RDP) from which RDWeb Access URL is opened. environment. For Hybrid deployment, Site to
Site VNET connectivity is mandatory. Also hybrid
And yes you guessed it correct, Azure Remote Apps collection needs Azure AD and on premises AD
uses RDS behind the scene! setup to make corporate users authenticate against
it. Additionally, in case of hybrid, you can bring your
own custom app based image VM to run in Azure
What is Azure Remote Remote Apps.
Apps?
More deployment choices can be found out here -
http://azure.microsoft.com/en-in/documentation/
Azure Remote Apps is a combination of Windows
videos/azure-remoteapp-cloud-deployment-
applications and RDS capabilities on Azure platform
overview/.

www.dotnetcurry.com/magazine 23
Preparing custom Remote Apps. These steps are very specific to our
scenario. Instead of using SQL Azure DB, you may use
image for Azure SQL Server on Azure VM or on- premises SQL server
depending on your application requirements. In that
Remote Apps Cloud case, you may not need to perform these steps at all.
only collection
Steps 3 to 6 are generalized steps and any production
In the next section, we will see a step by step Azure Remote Apps cloud collection deployment will
process to run our own custom desktop application need it.
developed in C# and with SQL Azure DB as backend;
in Azure Remote Apps Cloud Only collection. Setup Azure Storage account
Earlier during the preview version of remote Apps, and Cloud Service
bringing custom applications based VM image
was only possible with Hybrid collection. Starting Login to Azure portal with your Microsoft account.
Sep 2014, now Cloud only collection also supports Then select the subscription of your choice.
custom application based VM image. Moreover the We need to have storage account created in our
custom image can be prepared in Azure itself (by scenario because the SocialClub.bacpac file is present
using Azure VM’s) and have it configured in Azure as of now on your local machine. To create a database
Remote Apps cloud only collection. in SQL Azure DB, we will be using Azure Portal.
However we can create/ import the database from
Following are the high level steps we will perform Azure Portal only if the .bacpac is present in Azure
going forward – storage account.

1. Create a cloud service and setup Azure storage Click on Browse > Data + Storage > Storage Account >
account and upload sample DB .bacpac to storage Classic Deployment Model > Create. Provide the values
for restore operation. (.bacpac file is present in the as shown here:
source code of this article)

2. Setup SQL Azure DB in Azure subscription

3. Create Azure VM based on RDS template

4. Configure application and create template image Click Create button to proceed with storage account
(in source code) creation.

5. Upload template image in Azure remote Apps

6. Create cloud only collection and consume the


application from Remote Apps.

The sample application we will be using was


downloaded from CodeProject and it has been
changed to suit our needs and demo of Azure
remote Apps. The final version of the sample
application download link is at the end of this
article.

Note – Steps 1 and 2 are not necessary for Azure

24 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Click on the Key icon of storage account and note After container creation, select it and click on
down the name and primary key which we will need “Upload” button. A file selection window will appear.
to create container and blob in storage account. Select the Social.Club.bacpac file path from your
local machine and click ok. This will create a blob
named as “SocialClub.bacpac”.

Similarly click on New > Compute > Cloud Service >


Create.

Now we need to upload the SocialClub.bacpac file


to blob within this storage account. I usually use
the free storage explorer known as Azure Storage
Explorer to perform most of the storage operations.
It is free and satisfies all basic storage operations
need. Alternative to this will be Visual Studio 2012
and above. Assuming you have installed Azure
Storage Explorer, click on “Add Account” button.
Provide the name of storage account and the
primary key we noted in the previous step, and click Provide the values as depicted below –
on Save.

Click on Create button to finish cloud service wizard.

Setup SQL Azure Server and


SQL Azure DB
In the Azure preview portal, we first need to setup
In Azure Storage Explorer, after successful SQL Server (PaaS). However standalone SQL server
connection, select “Blob Containers” -> “New”. A pop creation is not available as of today unless a
up will appear wherein put the container name as single DB exists in it. Therefore we will create Test
“dbbackup” and Access Level as “Off:No anonymous database along with server. After server creation, we
access”. Click create. will delete the Test database and create our own
SocialClub database.

In Azure Management Portal click on New > Data


+ Storage > SQL Database. Provide the values of
server configuration settings as shown here -

www.dotnetcurry.com/magazine 25
Click on “Show Firewall Settings”. The firewall
settings will list current machine IP address
automatically. Click on “Add Client IP” and then
“Save” button to make sure that SQL server DB is
accessible from the local machine.

Now open the app.config file of the project


SocialClub.Desktop and replace the name of server,
database, username and password in connection
The rest of the values is as shown here – string. A sample connection string would be as
follows –

connectionString="Server=
tcp:dncsqlserver.database.windows.net,
1433;Database=SocialClub;
User ID=kunal@dncsqlserver;
Password=<YourPasswordGoesHere>;
Trusted_Connection=False;
Encrypt=True;Connection Timeout=30;"
Click on create to finish SQL server DB creation
wizard.
This completes the SQL server DB configuration for
our scenario.

Create Azure VM based on


Remote Desktop Session
Host template
In this step, we will create a VM template image
that can be used to run our sample desktop
After SQL Server creation, open the database Test application of SocialClub. This step is nothing
that we created in above steps and since we don’t but creating Azure remote app image based on
need it, delete it by clicking on Delete button in Azure VM. However if you look at the prerequisites
management portal. and steps mentioned in this link, creating custom
image based on Azure VM is complex. Therefore
To import the actual database, open Resource group to relieve the user from this cumbersome job,
“DNCResourceGroup” in Azure portal. Open the Azure provides you ready base template VM that
server “dncsqlserver”. Select the values as shown satisfies all prerequisites of Remote App image
below to import the SocialClub.bacpac –

26 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


and on top of it, you can have it customized for Configuration page, provide the following values
your needs. Therefore we will use the same one as and click Next to continue –
recommended which saves you from many complex
steps.

Note: For creating VM, we should use the New


Azure Preview portal (https://portal.azure.com). In the next screen, select the check box “Install the
However RemoteApps and the template image of VM agent” and click on Complete to start the VM
Remote Desktop Session Host as of this writing is creation.
not available on preview portal. In future it will be
available on preview portal but for this article we Once the VM is in running state, download the RDP
have to fall back to full management portal (http:// file by clicking on “Connect” button in management
manage.windowsazure.com). So by the time you portal and login with RDP credentials that was
read this article and proceed, check to see if remote provided during provisioning. Now we need to copy
apps is available on preview portal. The steps would our sample SocialClub application on this VM so
be similar and will not change to a great extent that we can publish the application later when
even if you are following new portal in the future. Azure Remote App is provisioned. Open Visual
Studio 2013 and build the sample application in
Open the full management portal and login with Release mode. After this, create a folder named
Microsoft account and select the subscription of SocialClub on ‘C’ drive of Azure VM and copy the
your choice. contents of Release folder. Please make a note
of the path of exe as we will need it later during
Click on New > Compute > Virtual Machine > From publishing programs in Azure Remote Apps
Gallery option. This will open up a pop up. Select collection. If you have created a folder on C drive
the VM image named as “Windows Server Remote with the same name, then your complete path will
desktop Session host” as shown here and click Next be – C:\SocialClub\SocialClub.Desktop.exe
to continue –
To verify everything is working, run the exe named
as SocialClub.Desktop.exe on Azure VM and confirm
if the application is working fine.

Now we are done with customization of our Azure


Remote App VM. All we need to do is to check the
VM against prerequisites and capture the template
image using Sysprep. As we have provisioned
our VM based on Remote Desktop Session Host
image, we will have a readymade PowerShell script
shortcut present on the desktop of VM named as
“ValidateRemoteAppImage”. Just run it and it will
start the entire process of validating the current VM
On the Virtual Machine configuration page, provide against remote app requirements. Once PowerShell
values as given below and click on Next to continue is through with VM validation, a prompt will popup
– in the same window asking for Sysprep. Input “Y” to
proceed ahead.

Now on the subsequent Virtual Machine

www.dotnetcurry.com/magazine 27
Now you must have observed that the original VM
has been deleted. However the associated OS disk
of original VM is still present. As we have captured
the image from this VM, we do not need this disk.
Moreover after a generalized process, it is not
recommended to use the same disk for provisioning
a new VM. Therefore instead of retaining this
unnecessary disk, just delete it. So click on “Disks”
tab and look out for the original VM OS disk. It must
Sysprep is a utility used for generalization of VMs. be having name of VM in it. So locate and delete the
After sysprep, you can capture the image of your disk from management portal by selecting option of
VM. You can then upload it to Azure Remote App “Delete the associated vhd”.
program to provision the required session host VM.
Once the sysprep process completes, the RDP will This completes the process of custom template VM
get disconnected automatically and status of the image creation.
VM will be shown as “Stopped” in the management
portal as seen here –
Upload VM image to Azure
Remote Apps
To upload VM image to Remote App, click on
Remote Apps option in management portal. Select
Click on the Capture button present at the bottom
the tab “Template Images” and select “Import or
pane of the portal and provide the values as shown
Upload a template image” or click on “Add” button
here –
as shown here –

Select the option “Import an image from your


Virtual Machine library (recommended)” and click on
Next to continue –

This process will capture the VM image and it will


be available under the Images tab in management
portal.
The image we had created earlier will appear in the
drop down. So click on the checkbox that has the
confirm option as shown here and click on Next to
continue.

28 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Creating remote app collection takes at least half
an hour to get ready for use. Once the collection
status becomes active, click on it and select the
“Publishing” tab. Click on the “Publish” button
present at the bottom and select the option “Publish
Program using Path”. A pop up will appear. Provide
the name of program as “Social Club App” and
path of the program which we had noted earlier
when we created custom image – “C:\SocialClub\
SocialClub.Desktop.exe”. Now click on Complete.

Provide the name of remote app template as


“DNCRemoteAppTemplateVM” and location as
“South East Asia” and click create. The image upload
to the Azure Remote App is an asynchronous
process and it will take a good amount of time
depending on your bandwidth connection. After a
successful upload operation, the image will appear Now we need to make sure that proper user access
as shown here – is given. Therefore click on “User Access” tab and
verify that your Microsoft account has access. In
case you wish to add access to another Microsoft
account, you can do so.

Now we are all set to create cloud collections in


Azure Remote App and publish our SocialClub
application.

Create Remote App Cloud


collection Now we are all set to use the application we
published.
Select New > App Services > Remote App > Quick
Create option. Provide the name as “DNCCollection”,
region as South East Asia, Plan as Standard
Using the Remote App
and most important, the template image as published application
“DNCREmoteAppTemplateVM”. Then click on “Create
Remote App Collection” option. The beauty of remote apps is that you can run/
access the published application on any platform
by using Remote App client. As shown below, the
url provides a download link from which you can
download any version of the client app –

www.dotnetcurry.com/magazine 29
application in cloud using Azure remote apps. Now
in next section we will particularly understand an
advanced scenario of Redirection which is very
common in enterprise corporate applications.

Advance topic -
Redirection and User
Profile Disk (UPD)
Azure remote app users get their own dedicated
persistent storage space of 50GB and it is stored in
a disk called as User Profile Disk (UPD). The user’s
configuration data, personal data and customization
data across various devices is stored in UPD. The
Open the link and click on the “download” menu. name of the disk is derived from the user name.
Download the client exe for Windows platform When a user saves any data, it always gets saved in
as I will be using it from my Windows 8 laptop. his Documents folder and it appears as if it is local
Alternatively you can have it downloaded as per to his device [which is not]. There is some excellent
your device platform. Once the client application information already present in the documentation
has downloaded, signin with your Microsoft Account about UPD at http://bit.ly/206TMxm .
which has access to remote app collection. After
successful login, the SocialClub application will Our focus in this section is to determine how
appear as shown below – exactly can you use this feature in your application.

In the same sample application, I have added a


button called as “Upload” under Manage tab. Click
on it and a file dialog will open. The functionality
of this button is simple. It allows a user to upload
a file which is a very common scenario in many
desktop based corporate or enterprise application.
So in this case, the file should get uploaded to the
user specific UPD. The code I have written on this
Double click on Social Club app and a RDP session button click is very straight forward and is shown
will get activated automatically and the login here –
screen of our Social Club application will appear.
Click on Search/ Manage Members menu which will OpenFileDialog fd = new
retrieve data from SQL Azure DB and populate the OpenFileDialog();
DialogResult result = fd.ShowDialog();
existing members, if any. Any any new members and
if (result == System.Windows.Forms.
data should get inserted in SQL Azure DB. DialogResult.OK)
{
This way you can download the client app on any string file = fd.FileName;
device running any platform such as iOS, Android, string fileName = Path.
GetFileName(file);
Windows and access the application. You don’t need
any installation, configuration to be done on your //get current logged in user
device and this is greatest benefit of Azure Remote MyDocuments folder
App. The application is running on remote computer string documentPath = Environment.
in Azure and it appears as if it is running on your GetFolderPath(Environment.
local machine. I hope the steps above must have SpecialFolder.MyDocuments);
//MessageBox.Show(documentPath);
given you good understanding of running desktop

30 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


File.Copy(file, documentPath + "\\" + on our local laptop, rather it is running in Azure
fileName); VM, hence desktop of Azure VM is displayed in
file dialog box which is perfectly fine. However
MessageBox.Show("File uploaded we want to save the document from the desktop
successfully");
} of our laptop to Document folders (which is UPD)
highlighted in green in the screenshot. In your case,
the green folder will be displaying your name.
It simply copies the file selected to current logged
in User’s Document folder. So in this way, by using
Environment.SpecialFolder.MyDocuments As the application is running in Azure VM, LOCAL
we are accessing UPD of current logged in user FOLDER and FILEs of laptop are not getting listed
in Azure remote app based application. Let’s say through file dialog box and to make it happen we
using the upload functionality of our Social Club need REDIRECTION.
application, we want to upload a PDF document
from our “desktop” to Azure remote App UPD based Redirection helps users to interact with Remote
Document folder. The screenshot of my desktop file Apps using the devices attached to their local
is as shown here – computer, laptop, tablet or phone. The devices
can be camera, printers, speakers, monitors and so
on. Of course by default, some of the redirection
services are already enabled when you use remote
app based application on your devices, however
drive redirection is not enabled by default and
that’s the reason local computer drives are not
shown in remote session. Once we enable the drive
redirection, local computer drives get mapped to
remote session and we would be able to access
local folders and files in remote session.

To enable drive redirection, we need to use


Azure PowerShell. Make sure that you have Azure
PowerShell latest version downloaded and installed
When we click on the Upload button in the on your local machine from http://bit.ly/1PPnfr9 .
application, the folders and files present on the
desktop of local laptop should be listed. We Once installed, open the Azure PowerShell window
click on Upload button and click on desktop as administrator. Run the following commands to
and unfortunately we don’t SEE LOCAL LAPTOP make a connection to your Azure subscription.
DESKTOP. Instead the desktop of Remote App
RDSH VM is displayed, which is running Social Club Add-AzureAccount
application in Azure as shown below –
Select-AzureSubscription –SubscriptionId
“YourSubscriptionId”

The azure subscription Id can be found out from the


“Settings” option in management portal as shown
below –

The reason of it showing Remote App VM desktop


is quite obvious as the application is not running

www.dotnetcurry.com/magazine 31
To enable drive redirection, run the following
command –

Set-AzureRemoteAppCollection -CollectionName
"dnccollection" -CustomRdpProperty
"drivestoredirect:s:*”

In your case, the collection name can be different


in the above command. This commands enables the
drive redirection to all the published apps within
Azure Remote App collection.

Now open the remote app client and open Social


Club application again. Click on Upload and then
you should be able to view the local drives of your
computer as shown here –

Go ahead and select the path of local desktop as c:\


Users\<YourLoginName>\Desktop\<YourFileName>
and the selected file will get copied to Documents
folder of Remote apps and “file uploaded
successfully” message will appear in the application.
This is how Redirection can be used to make remote
app communicate with local devices.

Is Redirection a new
concept?
Redirection is not new. It is already being used with
RDP files. For example, get a .rdp file and right click
on it and select “Open With Notepad”.
As you can see, redirection settings already exist
Once the RDP file is open in notepad you will see in RDP file and you can change it from notepad
something similar to the following – and save it. In case of remote app, we are changing
the same setting but through PowerShell. The
highlighted block in the above screenshot shows
drive redirection settings. Similarly there are
many other settings that can be changed through

32 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


redirection in Azure Remote apps. Learn more about
redirection at http://bit.ly/1kH396F .

Conclusion

In this article, we saw how Microsoft Azure Remote


Apps features can run desktop application. We also
saw the benefits associated with running desktop
apps in the Cloud. With the help of redirection, we
saw how to make remote app based application
more user interactive and device independent,
thereby enabling true BYOD (Bring Your Own
Device) environment for users

Download the entire source code from GitHub at


bit.ly/dncm21-azuremoteapps

About the Author

Kunal Chandratre is a Microsoft Azure


MVP and works as an Azure Architect in
a leading software company in (Pune)
India. He is also an Azure Consultant to
various organizations across the globe
for Azure support and provides quick
start trainings on Azure to corporates
and individuals on weekends. He
regularly blogs about his Azure
experience and is a very active member
in various Microsoft Communities
kunal and also participates as a ‘Speaker’
chandratre in many events. You can follow him
on Twitter at: @kunalchandratre
or subscribe to his blog at http://
sanganakauthority.blogspot.
com

www.dotnetcurry.com/magazine 33
Using
AngularJS with Bower and
RequireJS in Visual Studio
M odern client-side application development demands modularity. Client-side modularity is
required to achieve separation of logic from the UI. To implement this modularity, we usually use
an MVC or MVVM framework to manage separate layers (in separate JavaScript files) for Models,
Controllers, Modules, Services etc.

AngularJS is a great framework for implementing client-side modularity with MVC support.

However as the application grows, managing JavaScript dependencies on a page becomes a challenge, as
you need to load your JavaScript by listing all <script> tags and their dependencies, in a particular order.
Any JavaScript developer who has managed multiple <script> tags on a page knows how tedious and error
prone the entire exercise is. In many cases, it also affects the performance of the app.

34 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


RequireJS is a JavaScript framework that enables Pre-requisites for the implementation
asynchronous loading of files and modules and can
come in very handy while managing dependencies
Here are some pre-requisites before you get started:
across different AngularJS components and loading
• Free Community Edition of Visual Studio 2013
them asynchronously. An alternative to RequireJS
http://bit.ly/dncvscommunity OR Visual Studio
is Almond.js, a stripped down version of RequireJS.
2015 http://bit.ly/dncvs15community
RequireJS is more popular compared to it.

• Node for Visual Studio (NTVS) https://github.


A simple overview of RequireJS com/Microsoft/nodejstools#readme

RequireJS is a JavaScript module and file loader. We • Git for Windows. This will be used for
start with each JavaScript file, listing the different downloading dependencies using Bower
files it depends on. RequireJS then recognizes https://git-for-windows.github.io/. This downloads
these dependencies and loads them in the correct an exe.
order. Since RequireJS manage dependencies on
the client-side, we no longer need to manually Note: Wherever you see Visual Studio in this article,
refer to all script references on an html page. it either means Visual Studio 2013 or Visual Studio
RequiresJS implements the AMD API (Asynchronous 2015. You can choose either, as per availability.
module definition API) and thus inherits all its
advantages which includes asynchronous loading
of dependencies and implicit resolution of Using Bower to Install
dependencies, amongst other uses. Dependencies for the project

RequireJS can be used both in browsers as well as with Step 1: Open Visual Studio and create an empty
server solutions like Node.js. ASP.NET project with the name NG_RequireJS as
shown in the following image:
Since RequireJS loads files asynchronously, the
browser starts its rendering process while waiting
for RequireJS to do its work, without any blocking.
This improves performance.

Note: If anybody is interested in looking at an


implementation of KnockoutJS with RequireJS, please
check here http://www.dotnetcurry.com/aspnet-
mvc/1180/html-data-grid-aspnet-mvc-using-
knockoutjs-jquery-requirejs

In this article, we will be using Bower to install


dependencies in this project; in our case - AngularJS
and RequireJS. Bower is a package manager for the
web. It manages frameworks, libraries etc. needed by
the web application. Although I have implemented Step 2: To install necessary dependencies for the
this application using Visual Studio 2015, you can project, open Node.js command prompt (Run as
also implement it using Visual Studio 2013. To learn Administrator) and follow these steps.
more about Bower, check this article http://www.
dotnetcurry.com/visualstudio/1096/using-grunt- - From the command prompt navigate to the project
gulp-bower-visual-studio-2013-2015 . folder.

- Install Bower for the project


- Now install RequireJS with the following
command: Bower install requirejs –save
- Initialize Bower. This will add bower.json file to the
project. By default, the file is added in the project
path which will not be displayed in the Solution
explorer. So to view the file, click on Show all files
on the toolbar of our Solution Explorer and you will
find the bower.json file. Right-click on the file and
select Include in project. This needs to be done for
all dependencies which will be added in the next
steps.
Step 3: Go back to the project in Visual Studio,
select Show All Files from the Solution Explorer
tool bar and you should now see bower_
components include in the project. The project will
be displayed as shown in the following image.

The above image shows bower init command which


will ask for options to be added in the bower.json
file. Please select options as per your application’s
requirements. For this article, we have selected
module options for amd, globals and node. Once
these options are selected and added, the
bower.json file will take the following shape:

The project will be added with bower.json.


bower.js will show dependencies as shown below:
- Install AngularJS with the following command:
Bower install angularjs –save

So far so good, we have added the necessary


infrastructure for the project. Now we will add the
necessary AngularJS components to the project.

36 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


In this controller, add a Get() method with the
Adding AngularJS components following code:

Step 4: In the solution, add a new empty Web API using ServiceProject.Models;
using System.Collections.Generic;
project of the name ServiceProject. We will be using
using System.Web.Http;
this API as a service provider project for making
http calls using Angular’s $http service. namespace ServiceProject.Controllers
{
public class ProductInfoAPIController
: ApiController
{
public IEnumerable<Product> Get()
{
return new ProductDatabase();
}
}
}

Using RequireJS

Step 7: In the NG_RequireJS project, add a new


folder of the name app. In this folder, add the
following JavaScript files:
Step 5: In this project, in the Models folder, add a
new class file with the following code: Main.js

require.config({
using System.Collections.Generic; paths: {
angular: '../bower_components/
namespace ServiceProject.Models angular/angular'
{ },
public class Product shim: {
{ 'angular': {
public int ProdId { get; set; } exports:'angular'
public string ProdName { get; set; } }
} }
});
public class ProductDatabase :
List<Product> require(['app'], function () {
{ require(['serv', 'ctrl'], function ()
public ProductDatabase() {
{ angular.bootstrap(document,
Add(new Product() ['app']);
{ProdId=1,ProdName="Laptop" }); });
Add(new Product() { ProdId = 2, });
ProdName = "Desktop" });
} The above script bootstraps RequireJS by
}
} calling require.config() function, passing in
a configuration object which contains path for
the AngularJS framework. Since AngularJS is an
Step 6: In the Controllers folder, add a new
external dependency here that is being managed
empty Web API Controller of the name
using Bower, we are specifying a relative path to
ProductInfoAPIController.
our bower_components directory. To make sure
that AngularJS is embedded correctly, we are using

www.dotnetcurry.com/magazine 37
RequireJS to assign AngularJS to the global variable }]);
angular. This is done using the attribute shim. We })
are using exports which defines global access to the
angular object, so that all JavaScript modules/files This code defines angular service of name serv,
can make use of this object. which makes call to the Web API service and
receives a response.
The above file also defines require() used for
loading the necessary modules asynchronously ctrl.js
along with the loading of the document (DOM).
require() loads the modules - app, serv and ctrl define(['app'], function (app) {
asynchronously. app.controller('ctrl',
['$scope','serv', function ($scope,
The following line: serv) {
loaddata();
angular.bootstrap(document, ['app']); function loaddata() {
var promise = serv.getdata();
..performs the same operation as the ng-app promise.then(function (resp) {
directive does. The reason we are using $scope.Products = resp.data;
$scope.Message = "Operation
angular.bootstrap() instead of ng-app is Completed Successfully...";
because the files are loaded asynchronously. If we }, function (err) {
use ng-app, there could be a possibility that when $scope.Message = "Error " + err.
AngularJS loads a module in the ng-app directive, status;
RequireJS may have not yet loaded the module. })
Hence we use angular.bootstrap() to initialize our };
}]);
app only when RequireJS has finished loading its });
modules. The first parameter to angular.bootstrap()
is the DOM element and the second parameter is
The above file contains code for declaring angular
the application module that is to be loaded. Here it
controller. This file has dependency on the angular
simply means that the app module will be loaded at
service. The above controller makes a call to
document level.
getData() function of the angular service. Once
the data is received from the service, it is stored in
App.js the Products $scope object.

define(['angular'],function (angular) { Step 8: On the project root, add an index.html with


var app = angular.module('app', []); the following markup and code:
return app;
}); <!DOCTYPE html>
<html>
The above file defines angular module of name ‘app’. <head>
The angular object declared through shim is passed <title>Using RequireJS with
Angular.js</title>
to it.
<meta charset="utf-8" />
<style type="text/css">
serv.js table, td,th {
border:double;
define(['app'], function (app) { }
app.service('serv', ['$http',function </style>
($http) { </head>
this.getdata = function () { <body ng-controller="ctrl">
var resp = $http.get('http:// <h1>Using RequireJS with Angular.js
localhost:4737/api/ProductInfoAPI'); </h1>
return resp;
} <table>

38 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


<thead> Run the application and the Index.html loads in the
<tr> browser with the following result:
<th>Product Id</th>
<th>Product Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="p in Products">
<td>{{p.ProdId}}</td>
<td>{{p.ProdName}}</td>
</tr>
</tbody>
</table>
<div>{{Message}}</div>
<script src="bower_components/requirejs/ Right click on the page > View source and you will
require.js" data-main="app/Main.js"> see all modules listed in order.
</script>
</body>
</html> Conclusion

Here the following line RequireJS is an awesome library for managing


<script src="bower_components/requirejs/ asynchronous module loading when the logic is
require.js" data-main="app/Main.js"> segregated in separate JavaScript files. It loads
</script> modules and the relevant dependencies in their
right order. Make sure you learn this library and use
..is used to initialize and load RequireJS. The data- it in a project containing multiple JavaScript files!
main attribute is used to load Main.js, the starting
point of our application. This attribute tells
require.js to load app/Main.js after require.js has Download the entire source code from GitHub at
loaded. Main.js configures Angular and other bit.ly/dncm21-require-angularjs
module dependencies.

This is how we eliminate the need to refer to all


JavaScript files in an HTML page using RequireJS.
About the Author
Running the Application
Mahesh Sabnis is a Microsoft MVP
in .NET. He is also a Microsoft
Run the application by setting multiple startup Certified Trainer (MCT) since
projects in Visual Studio, as shown in the following 2005 and has conducted various
image: Corporate Training programs for
.NET Technologies (all versions).
Follow him on twitter
@maheshdotnet. Mahesh blogs
regularly on .NET Server-side &
other client-side Technologies at

mahesh sabnis bit.ly/HsS2on

www.dotnetcurry.com/magazine 39
Create Your First
Diagnostic Analyzer
in Visual Studio 2015
This article talks about creating custom Diagnostic Analyzers in Visual
Studio 2015. If you are new to the concept of Diagnostic Analyzers, read the
"Introduction to Diagnostic Analyzers in Visual Studio 2015" article over
here http://www.dotnetcurry.com/visualstudio/1197/
diagnostic-analyzers-visual-studio-2015

40 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


D
iagnostic analyzers are a great new On creating a project, Visual Studio detects and will
extensibility feature in Visual Studio 2015 offer to install the missing feature for you.
for performing static code analysis. Most
developers will probably settle with using the
ones provided by Microsoft and third party vendors.
Nevertheless, there are scenarios that warrant
development of custom diagnostic analyzers,
such as enforcing coding guidelines in a company.
Keeping this customization in mind, Microsoft has
put a lot of effort in making the initial experience
as pleasant as possible. This article will walk you
through the process of creating a simple diagnostic
Figure 2: Install missing feature directly from Visual Studio
analyzer on your own.

Software Prerequisites Trying Out the Default


Diagnostic
To use diagnostic analyzers, Visual Studio 2015 is
required: Community, Professional or Enterprise We will start out by creating a new Visual Studio
edition to be exact. Although this might suffice for project from the template and giving it a test run.
development, the experience can get much better
by installing the .NET Compiler Platform SDK. It Run Visual Studio 2015 and create a new project
includes two components that are important for our based on the Diagnostic with Code Fix (NuGet + VSIX)
task: template (you can find it in Templates > Visual C#
> Extensibility node). It will create a solution with
• Visual Studio project template for a diagnostic three projects for you (DncAnalyzer part of each
analyzer, and name will be replaced with whatever name you
choose for your project):
• Roslyn Syntax Visualizer for interactive syntax tree
exploration. • Portable class library project DncAnalyzer with the
actual analyzer code.
To follow the examples in this article, you will need
to have this extension installed in your copy of • Unit test project DncAnalyzer.Test with unit tests
Visual Studio 2015. for the analyzer.

The template we are going to use will also create • VSIX project DncAnalyzer.VSIX for packaging the
a Visual Studio extension. Therefore your Visual analyzer as a Visual Studio extension.
Studio installation will need to include the Visual
Studio Extensibility Tools. Visual Studio will conveniently preselect the last
one as a startup project. When you run the solution
from within Visual Studio, it will perform the
following steps for you:

• Compile the analyzer.


• Create a Visual Studio extension from it.
Figure 1: Visual Studio Extensibility Tools feature in Visual
• Run a new instance of Visual Studio.
Studio setup
• Install the created extension in it.
You do not have to worry if you have already
installed Visual Studio 2015 without this feature. To try out the analyzer, you can create a new class

www.dotnetcurry.com/magazine 41
library project inside this Visual Studio instance. It have not removed it yet. You can save a lot of time
should immediately report a warning and offer you by testing your code with unit tests for the majority
a fix for it. of development time and only run it in Visual
Studio towards the end to make sure it behaves as
expected.

Validation of Regular
Expressions
Although the template has already provided us with
Figure 3: Default diagnostic analyzer in action a working diagnostic analyzer, this is a rather simple
example. To make it more interesting, let us set a
Even debugging works flawlessly in this setup. more ambitious and useful final goal: validating
Switch back to your first Visual Studio instance and regular expression patterns appearing in source
open DiagnosticAnalyzer.cs from DncAnalyzer project. code as string literals. In order to have it working
Set a break point in the first line of AnalyzeSymbol by the end of this article, we will actually have to
method. Now switch back to the second instance limit the scope a little bit. Instead of covering all
and change the class name. Code execution possible cases, we will settle with inspecting only
should stop at the line with the breakpoint. This the following one:
makes it easy to troubleshoot a diagnostic during
development. using System.Text.RegularExpressions;

namespace RegexSample
The only downside is a relatively long Visual {
Studio start-up time, which makes the typical cycle public class Class1
of finding a problem, fixing it and restarting the {
project, slower than one would wish. This is where public void Foo()
{
the unit test project can prove helpful. To try it, Regex.Match("", "[");
resume the execution from the breakpoint and close }
the second Visual Studio instance. Run the test in }
the first Visual Studio instance by navigating to Test }
> Run > All Tests in the main menu. Test Explorer will
show up with test results. To be exact, we will inspect all calls to
Regex.Match method, having the second argument
(i.e. the regular expression pattern) as a string
literal.

Instead of jumping directly into writing code, we


will first take advantage of a very useful tool,
bundled with .NET Compiler Platform SDK, the
Roslyn Syntax Visualizer. To see it in action, create a
new class library project, and add the above code
into it. Now, navigate to View > Other Windows >
Syntax Visualizer to open it. If you try moving the
Figure 4: Unit test results in Test Explorer cursor to different spots in the code editor window,
you will notice that the syntax visualizer tree view
If you right click TestMethod2 and select Debug is keeping in sync, always focusing on the currently
Selected Tests from the context menu, the execution selected token. It works the other way around, as
should again stop at the breakpoint, assuming you well: whenever you select a node in the tree view,

42 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


the corresponding part of source code will be calls.
selected in the code editor.
• Out of these, the ones that interest us are only
those which are invoking Regex.Match method with
two arguments.

• Even that is not specific enough: we will only


analyze calls with a string literal as its second
argument.

Figure 5: Regex.Match method call in syntax visualizer The second step will be much easier. We will
retrieve the value of the literal and verify that it is a
valid regular expression pattern. This can easily be
Select the Regex.Match method call as seen in
done using .NET’s Regex class.
Figure 5 and fully expand it in the tree view to get a
better sense of the code that we will be inspecting.
You will notice that the nodes in the tree view are
of three different colors:
Implementing the Idea
With the plan in place, we can get to work. Switch
• Blue color represents intermediate nodes in the back to the Visual Studio instance with the default
syntax tree, i.e. higher level language constructs diagnostic analyzer project open (as created at the
beginning of this article). We are going to use it as
• Green color represents tokens, e.g. keywords, our starting point.
names, and punctuation
Before we start implementing the analysis
• Red color represents trivia, i.e. formatting algorithm, we should modify the identity of the
characters that do not affect semantics. analyzer to match our intentions. The relevant
code can be found at the beginning of the
To get an even better view of the sub tree, right DncAnalyzerAnalyzer class:
click on the InvocationExpression node in the tree
view and click on View Directed Syntax Graph. This public const string DiagnosticId = "DncAnalyzer";
will render it nicely in a separate window.
// You can change these strings in
the Resources.resx file. If you do not
want your analyzer to be localize-able,
you can use regular strings for Title
and MessageFormat.

private static readonly


LocalizableString Title = new
LocalizableResourceString
Figure 6: InvocationExpression syntax tree (nameof(Resources.AnalyzerTitle),
Resources.ResourceManager,
Looking at this image, we can formulate the basic typeof(Resources));
idea of how to implement the analyzer. The first private static readonly
step is to recognize the language construct of LocalizableString MessageFormat = new
interest, i.e. the one corresponding to this syntax LocalizableResourceString
tree: (nameof(Resources.
AnalyzerMessageFormat), Resources.
ResourceManager,
• We will need to inspect all InvocationExpression typeof(Resources));
nodes, because they are representing the method

www.dotnetcurry.com/magazine 43
private static readonly continue by specifying when Visual Studio should
LocalizableString execute our custom analyzer code. This is how we
Description = new will change the Initialize method:
LocalizableResourceString
(nameof(Resources.AnalyzerDescription), public override void
Resources.ResourceManager, Initialize(AnalysisContext context)
typeof(Resources)); {
context.
private const string Category = RegisterSyntaxNodeAction(AnalyzeSyntax,
"Naming"; SyntaxKind.InvocationExpression);
}
private static DiagnosticDescriptor Rule
= new DiagnosticDescriptor(DiagnosticId, The previously used RegisterSymbolAction would
Title, MessageFormat, Category, have allowed us to do analysis at the level of a
DiagnosticSeverity.Warning,
symbol, which was fine for the default analyzer,
isEnabledByDefault: true, description:
Description); checking the casing of a class name. We are
interested in a full node in the syntax tree; hence,
We will do the following changes: we will call RegisterSyntaxNodeAction and specify
the type of node that interests us by passing it
SyntaxKind.InvocationExpression.
• Set DiagnosticId to "DNC01". This is the unique
identifier of our analyzer.
The first argument is the name of the callback
method that will be called. This is where we
• Set Category to "Usage". There is no predefined
will put all of our logic. We can delete the
list of supported categories. It is best you check
existing AnalyzeSymbol method and create a new
existing analyzers and choose one from there.
AnalyzeSyntax method with the following signature:

• Set the default severity to error by changing private void


the fifth argument of the DiagnosticDescriptor AnalyzeSyntax(SyntaxNodeAnalysisContext
constructor call to DiagnosticSeverity.Error. As you context)
can see, all values describing the analyzer are {
passed to this constructor. }

We still have not changed all the texts, describing Since in our call to RegisterSyntaxNodeAction,
our analyzer. Since they are localizable, we need to we have specified that we are only interested in
open the Resources.resx file and change them there: InvocationExpression, we can safely assume that
our method will only be called for this type of
• AnalyzerTitle is a short name for the error. We will nodes:
set it to: "Regular expression is invalid" var invocationExpression =
(InvocationExpressionSyntax)context.
• AnalyzerDescription is a longer description of what Node;
is being analyzed. We will set it to: "Pattern must be
a valid regular expression." We can expect Visual Studio to call our method
a lot; therefore, it is important to make it as
• AnalyzerMessageFormat is the template for the efficient as possible and to avoid any unnecessary
actual error message. It will be passed to processing. Very likely, only a small part of method
String.Format along with your additional data, calls will actually be calls to Regex.Match. To stop
when you report the error. We will set it to: "Regular processing those as soon as possible, we will check
expression is invalid: {0}" which method is being called in two phases:

Once we are through with the formalities, we can var memberExpresion =


invocationExpression.Expression as

44 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


MemberAccessExpressionSyntax; will be called in the compiled code as well:
if (memberExpresion?.Name?.ToString() !=
"Match") return; try
{
var memberSymbol = System.Text.RegularExpressions.Regex.
context.SemanticModel. Match("", regex);
GetSymbolInfo(memberExpresion).Symbol; }
if (memberSymbol?.ToString() != catch (ArgumentException e)
"System.Text.RegularExpressions.Regex. {
Match(string, string)") return; var diag = Diagnostic.Create(Rule,
regexLiteral.GetLocation(),
First, we only check the name of the method. In the e.Message);
unlikely case that it is actually named Match, we do context.ReportDiagnostic(diag);
}
a lookup into the symbol table and check the full
method signature. Of course, symbol table lookup is
much slower than a simple string comparison. If any Notice how the error is reported when the regular
of the two checks fails, we quietly exit the method expression is invalid. We create a report by passing
and stop further analysis. all the relevant data to its factory method: Rule
with full analyzer description, location in the code
corresponding to the erroneous node, and the
Being sure that the right method is called, we
arguments for our error message format.
continue by checking whether the second argument
is really a literal:
Our diagnostic analyzer is complete. Before trying
var argumentList = invocationExpression. it out, delete the CodeFixProvider.cs file from the
ArgumentList as ArgumentListSyntax; project to prevent the default code fix from popping
if ((argumentList?.Arguments.Count ?? 0) up in Visual Studio. You can now run the solution.
!= 2) return; Once a new instance of Visual Studio starts, open
var regexLiteral = argumentList. the regular expression sample which we have been
Arguments[1].Expression as analyzing using the Roslyn Syntax Visualizer. The
LiteralExpressionSyntax; invalid regular expression should be marked as
if (regexLiteral == null) return; error.

Having already checked the full method signature


makes counting the number of arguments
redundant in this case. Keep in mind though, that
we really do not want the analyzers to throw
any exceptions. Therefore, if there was even the
slightest doubt that retrieving the second argument
from the array could throw one, it is better to do a
second check, especially if it is as efficient as this
one.
Figure 7: Invalid regular expression detected

At this point in code, we can be sure that the


method call exactly matches what we are interested Conclusion
in. We still have to retrieve the value of the literal:
As you can see, thanks to Roslyn, static code
var regexOpt = context.SemanticModel. analysis became more accessible than it was ever
GetConstantValue(regexLiteral); before. Admittedly, our example is still simple, and
var regex = regexOpt.Value as string; extending it to cover all possible cases would be a
lot of work. Nevertheless, such a low barrier to entry
We will leave the validation of the regular should encourage many developers to try diagnostic
expression pattern to the Regex class. This is how it analyzer development themselves.

www.dotnetcurry.com/magazine 45
I am sure some of them will end up developing
diagnostic analyzers, which we will be using every
day. Dear reader, maybe you will be one of them!

Download the entire source code from GitHub at


bit.ly/dncm21-vs-diag-analyzer

About the Author


Damir Arh has many years
of experience with Microsoft
development tools; both in complex
enterprise software projects and
modern cross-platform mobile
applications. In his drive towards
better development processes,
he is a proponent of test driven
development, continuous integration
and continuous deployment. He
shares his knowledge by speaking at
damir arh local user groups and conferences,
blogging, and answering questions
on Stack Overflow. He is an awarded
Microsoft MVP for .NET since 2012.

46 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Universal Windows 10
Platform (UWP) Music
App for
Windows Phone & Raspberry Pi2

Windows 10 introduces an entirely new way of developing apps


targeting multiple devices and it is called UWP apps or Universal
Windows Platform apps. Instead of creating separate apps for
different platforms, UWP apps run across all major platforms with
minor code changes.

This article covers part 2 of our journey to develop a Windows 10 Universal App (UWP) that will run on
most of the devices without any code change. In Part 1 http://bit.ly/dnc-win10-soundcloud-1 , I wrote
how the new Windows 10 controls allow us to target a wide variety of Windows devices with minimal
code. With Adaptive Triggers and Custom App shell, we developed a simple Sound Cloud player that
adapts the UI based on the size of the screen.

In this article, we will improve our app by adding more features and changing existing code to support
Background Audio and Media Transport Controls. We will also deploy our app to both a Windows Phone
and Raspberry Pi2 without any code changes.

Disclaimer: This article contains a lot of code which contains comments wherever needed explaining what the
code does.

48 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


- Open the Package Manifest file for MusicPlayer
Project Setup project and Navigate to declarations tab. Add
the Background Tasks declaration and set
The previous sample played the first track from BackgroundAudioTask.MyBackgroundAudioTask as the
the “likes” playlist from SoundCloud but it did not Entry Point value. Make sure only “Audio” is checked
support Background Audio and had the following under Supported Task Types.
limitations:

1. Minimizing App stopped the play back


2. Default Media Controls (Keyboard, Screen etc)
were hidden
3. Media Controls did not show Song, Album art etc

We will add Background Audio support to our App


and fix the above limitations. For Windows 10
development, it’s much easier to enable Background
Audio and Manage playlist. To read more about the
details of the implementation, read Background
Audio (http://bit.ly/1H9mf9Y) MSDN documentation.
To make it simpler, we will use the sample
Background Audio App provided by Microsoft - Move SoundCloudUser.cs , SoundCloudTrack.cs and
which can be downloaded from GitHub (http://bit. SoundCloudCreatedWith.cs from MusicPlayer project
ly/1NzKtPv) . to BackgroundAudioShared project and update the
namespace names. Your solution explorer should
Let us perform the following steps. I am assuming now look like the following:
you have downloaded the source code of the
previous article & Microsoft’s Github project.

- Add the BackgroundAudioShared and


BackgroundAudioTask projects from the sample
project to our solution, and add references to these
projects in MusicPlayer App. Your Solution Explorer
should look like the following:

MusicPlayer
- Make the following changes to App.xaml.cs to
declare a new SoundCloudUser object which we

www.dotnetcurry.com/magazine 49
will use later to display profile details. expression/blend/2008"
xmlns:mc="http://schemas
.openxmlformats.org/
public static string SoundCloudClientId markup-compatibility/2006"
= "<YOUR CLIENT ID>"; mc:Ignorable="d"
public static int SCUserID = 0; xmlns:data="using:
public static string SoundCloudLink = BackgroundAudioShared">
"http://api.soundcloud.com/"; <Page.Resources>
public static string SoundCloudAPIUsers <DataTemplate x:Key=
= "users/"; "ImageOverlayTemplate"
public static List<SoundCloudTrack>
likes = new List<SoundCloudTrack>(); x:DataType="data:SoundCloudTrack">
public static int nowplayingTrackId = 0; <StackPanel Height="130"
public static SoundCloudUser SCUser { Width="190" Margin="4,4,4,8">
get; set; } <TextBlock Text="{x:Bind title}"
Margin="8,4" Width="186"
- Make the following code changes to Style="{StaticResource
BaseTextBlockStyle}"
AppShell.xaml.cs to change menu items HorizontalAlignment="Left"/>
<Image Source="{x:Bind
// Declare the top level nav items AlbumArtUri}"
private List<NavMenuItem> navlist = new Margin="8,0,8,8"
List<NavMenuItem>(new[] Stretch="UniformToFill"/>
{ </StackPanel>
new NavMenuItem() </DataTemplate>
{ </Page.Resources>
Symbol = Symbol.Play, <Grid Background="{ThemeResource
Label ="Now Playing", ApplicationPageBackgroundThemeBrush}">
DestPage = typeof(NowPlaying) <GridView x:Name="grdLikes"
}, ItemTemplate="{StaticResource
new NavMenuItem() ImageOverlayTemplate }"
{ IsItemClickEnabled="True"
Symbol = Symbol.Emoji2, IsSwipeEnabled="False"
Label = "Likes", CanDragItems="False"
DestPage = typeof(Likes) SelectionMode="None"
}, ItemClick="grdLikes_ItemClick" />
new NavMenuItem() </Grid>
{ </Page>
Symbol = Symbol.Contact,
Label = "Me", In the above code, we have added a GridView control
DestPage = typeof(Me) and a Data template which will be used to display a
}
list of all the Tracks added to our “Likes” playlist.
});

- Add a new Blank Page to the project and name it - Add the following code to likes.xaml.cs.
Likes.xaml I have deliberately removed the namespaces to save
space but you can always look up the source code of
- Add the following code to Likes.xaml this article for the same.

namespace MusicPlayer
<Page {
x:Class="MusicPlayer.Likes" /// <summary>
xmlns="http://schemas.microsoft.com/ /// An empty page that can be used on
winfx/2006/xaml/presentation" its own or navigated to within a Frame.
xmlns:x="http://schemas.microsoft. /// </summary>
com/winfx/2006/xaml" public sealed partial class Likes :
xmlns:local="using:MusicPlayer" Page
xmlns:d="http://schemas.microsoft.com/ {

50 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


public Likes() /// An empty page that can be used on
{ its own or navigated to within a Frame.
this.InitializeComponent(); /// </summary>
this.Loaded += Likes_Loaded; public sealed partial class MainPage :
} Page
{
private void Likes_Loaded(object public MainPage()
sender, RoutedEventArgs e) {
{ this.InitializeComponent();
grdLikes.ItemsSource = App.likes; this.Loaded += MainPage_Loaded;
} }

private void grdLikes_ItemClick private void MainPage_Loaded(object


(object sender, ItemClickEventArgs e) sender, RoutedEventArgs e)
{ {
var song = e.ClickedItem as //Get User
SoundCloudTrack; GetUserDetails();
MessageService. }
SendMessageToBackground
(new TrackChangedMessage(new private async void GetUserDetails()
Uri(song.stream_url))); {
try
} {
string responseText = await
private void grdLikes_ GetjsonStream(App.SoundCloudLink
SelectionChanged(object sender, + App.SoundCloudAPIUsers
SelectionChangedEventArgs e) + "shoban-kumar" + ".json?client_id="
{ + App.SoundCloudClientId);
App.SCUser = JsonConvert.
} DeserializeObject<SoundCloudUser>
} (responseText);
}
App.SCUserID = App.SCUser.id;
In this code, we have done the following:
//Get Likes
GetLikes();
1. Set the ItemsSource property to global App.likes }
property. This will populate the Gridview with the list catch (Exception ex)
of tracks. {
...
}
2. When an Item (Track) is clicked in the GridView, }
we also load the Track details and Send a Message
to our Background Task which will control the media private async void GetLikes()
playback. {
try
{
- Make the following code changes to string responseText = await
MainPage.xaml.cs to populate the SoundCloudUser GetjsonStream(App.SoundCloudLink
object which is declared in App.xaml.cs + App.SoundCloudAPIUsers
+ App.SCUserID +
"/favorites.json?client_id="
// The Blank Page item template is + App.SoundCloudClientId);
documented at http://go.microsoft.com/ App.likes = JsonConvert.
fwlink/?LinkId=402352&clcid=0x409 DeserializeObject<List
<SoundCloudTrack>>(responseText);
namespace MusicPlayer
{ //remove songs which do not have
/// <summary> stream url

www.dotnetcurry.com/magazine 51
App.likes = App.likes. <StackPanel HorizontalAlignment=
Where(t => t.stream_url != null). "Center">
ToList<SoundCloudTrack>(); <Ellipse Height="250" Grid.Row="0"
Width="250" x:Name="Albumart" >
//add "?client_id=" + App. <Ellipse.Fill>
SoundCloudClientId to stream url <ImageBrush x:Name="profilePhoto"
App.likes = App.likes.Select(t ImageSource="Assets\Albumart.png"
=> { t.stream_url += "?client_id=" Stretch="UniformToFill" />
+ App.SoundCloudClientId; return t; </Ellipse.Fill>
}).ToList<SoundCloudTrack>(); </Ellipse>
loginProgress.IsActive = false;
...
AppShell shell = Window.Current. <TextBlock x:Name="txtFollowing"
Content as AppShell; Text="" Style="{StaticResource
shell.AppFrame.Navigate HeaderTextBlockStyle}" />
(typeof(NowPlaying));
} <TextBlock Text="Followers"
catch (Exception ex) Style="{StaticResource
{ TitleTextBlockStyle}"
... Foreground="Gray" />
}
} <TextBlock x:Name="txtFollowers"
Text="" Style="{StaticResource
public async Task<string> HeaderTextBlockStyle}" />
GetjsonStream(string url) //Function
to read from given url </StackPanel>
{ </Grid>
HttpClient client = new </Page>
HttpClient();
In the above code, we added few controls to display
HttpResponseMessage response = await the Profile Photo, Name, Website and some other
client.GetAsync(url);
details from SoundCloud.
HttpResponseMessage v = new
HttpResponseMessage();
return await response.Content. Add the following code to Me.xaml.cs to populate
ReadAsStringAsync(); profile details from the new SoundCloudUser object.
}
}
} ...

- Add a new Blank Page named Me.xaml and private void Me_Loaded(object sender,
add the following code to the xaml file: RoutedEventArgs e)
{
if (App.SCUser != null)
<Page {
x:Class="MusicPlayer.Me" txtFirstname.Text = Convert.
xmlns="http://schemas.microsoft.com/ ToString(App.SCUser.first_name);
winfx/2006/xaml/presentation" txtlastname.Text = Convert.
xmlns:x="http://schemas.microsoft.com/ ToString(App.SCUser.last_name);
winfx/2006/xaml" txtWebsite.Text = Convert.
xmlns:local="using:MusicPlayer" ToString(App.SCUser.website);
xmlns:d="http://schemas.microsoft.com/ txtCity.Text = Convert.ToString(App.
expression/blend/2008" SCUser.city);
xmlns:mc="http://schemas.openxmlformats txtCountry.Text = Convert.
.org/markup-compatibility/2006" ToString(App.SCUser.country);
mc:Ignorable="d"> txtFollowers.Text = Convert.
ToString(App.SCUser.followers_
<Grid Background="{ThemeResource count);
ApplicationPageBackgroundThemeBrush}"> txtFollowing.Text =

52 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Convert.ToString(App.SCUser.followings_ this.InitializeComponent();
count); this.Loaded += NowPlaying_Loaded;
profilePhoto.ImageSource = new }
BitmapImage(new Uri(
App.SCUser.avatar_url)); private void NowPlaying_Loaded
(object sender, RoutedEventArgs e)
} {
} backgroundAudioTaskStarted
} = new AutoResetEvent(false);
} if (!IsMyBackgroundTaskRunning)
{
- Now add the following code changes to StartBackgroundAudioTask();
NowPlaying.xaml.cs. Please check the source code as }
else
the code is too big to fit here.
{
//Start playback if Paused.
// The Blank Page item template is ...
documented at http://go.microsoft.com/ }
fwlink/?LinkId=234238 }
private void
namespace MusicPlayer StartBackgroundAudioTask()
{ {
public sealed partial class NowPlaying //check source code
: Page ...
{ }
private bool
isMyBackgroundTaskRunning = false; private void
AppShell shell = AddMediaPlayerEventHandlers()
Window.Current.Contentas AppShell; {
private AutoResetEvent ...
backgroundAudioTaskStarted; }

private bool IsMyBackgroundTaskRunning protected override void


{ OnNavigatedTo(NavigationEventArgs e)
get {
{ ...
if (isMyBackgroundTaskRunning) }
return true;
async void BackgroundMediaPlayer_
string value = MessageReceivedFromBackground(object
ApplicationSettingsHelper. sender,MediaPlayerDataReceivedEventArgs e)
ReadResetSettingsValue {
(ApplicationSettingsConstants. ...
BackgroundTaskState) as string; backgroundAudioTaskStarted.Set();
return;
if (value == null) }
{ }
return false;
} public int GetSongIndexById(Uri id)
else {
{ return App.likes.FindIndex(s => new
... Uri(s.stream_url) == id);
return isMyBackgroundTaskRunning; }
}
} protected override void
} OnNavigatedFrom(NavigationEventArgs
e)
public NowPlaying() {
{ if (isMyBackgroundTaskRunning)

www.dotnetcurry.com/magazine 53
{ SendMessageToBackground(new
ApplicationSettingsHelper. SkipNextMessage());
SaveSettingsValue( }
ApplicationSettingsConstants.
BackgroundTaskState, private void btnPrev_Click(object
BackgroundTaskState.Running. sender, RoutedEventArgs e)
ToString()); {
} //Send message to background task
base.OnNavigatedFrom(e); MessageService.
} SendMessageToBackground(new
SkipPreviousMessage());
private Uri GetCurrentTrackId() }
{ }
... }
}
In the above code, we have done the following:
private async void LoadTrack(
SoundCloudTrack currentTrack)
{ 1. As soon as the Page is loaded, we check if the
... BackgroundTask is currently running and toggle
} playback.

private void btnPlay_Click(object


2. If this is the first time or the Background task is
sender, RoutedEventArgs e)
{ not running, we start a new BackgroundTask and
if (IsMyBackgroundTaskRunning) enable App to Background Task messaging.
{
if (MediaPlayerState.Playing 3. This allows us to control the Media Player from
== BackgroundMediaPlayer.Current.
our UI as well as get notified if Media controls
CurrentState)
{ (Keyboard, Phone Hardware buttons etc) are
BackgroundMediaPlayer.Current. pressed, which can be used to display correct Track
Pause(); details if our App is in the foreground.
}
else if (MediaPlayerState.Paused
4. We also send respective Next/Previous Message
== BackgroundMediaPlayer.Current.
CurrentState) to Background Task to move between songs in
{ Playlist.
BackgroundMediaPlayer.Current.
Play();
} BackgroundAudioTask
else if (MediaPlayerState.Closed
== BackgroundMediaPlayer.Current.
CurrentState) - Please check the source code to observe the code
{ changes to MyBackgroundAudioTask.cs file.
StartBackgroundAudioTask();
} You will observe in the source code that we updated
} the song model with SoundCloudTrack custom
else
{ object, handled messages from Foreground App,
StartBackgroundAudioTask(); saved current Track Id and changed tracks.
}
}
BackgroundAudioShared
private void btnNext_Click(object
sender, RoutedEventArgs e)
{ - Update SoundCloudUser.cs file with the following
//Send message to background task code to add new properties which are used in
MessageService. Me.xaml file in MusicPlayer project.

54 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


namespace BackgroundAudioShared
{
public class SoundCloudUser
{
public int id { get; set; }
public string permalink { get; set; }
public string username { get; set; }
public string avatar_url { get; set; }
...
public int followers_count
{ get; set; }
public int followings_count
{ get; set; }
}
}

- Change UpdatePlaylistMessage.cs to use


SoundCloudTrack object.

namespace BackgroundAudioShared.Messages
{
[DataContract]
public class UpdatePlaylistMessage
{
public UpdatePlaylistMessage
(List<SoundCloudTrack> songs)
{
this.Songs = songs;
}
Clicking any Track in Likes page will change the
[DataMember]
public List<SoundCloudTrack> Songs; “now playing” Track to the selected track. Press any
} of the hardware buttons to show Media Controls.
}

Testing our Windows 10 Sound


Cloud Music Player app
Press debug and test the changes and if there are
no compile errors, you should see the changes in Minimize the Music Player app and enjoy the music.
Profile, Likes and Now Playing Pages as shown here.
Windows 10 Application
Deployment tool
Windows 10 Application Deployment tool
(WinAppDeployCmd.exe) is a command line utility
that can be used to remotely deploy Apps to
Windows Mobile Devices.

Let us try to deploy Music Player App to a Windows


Mobile.

www.dotnetcurry.com/magazine 55
- Open Command Prompt and navigate to C:\ [YOUR REMOTE IP HERE] and press enter to install the
Program Files (x86)\Windows Kits\10\bin\x86 App Package.

- Type WinAppDeployCmd devices and press enter to - Wait for the App to be installed in your Windows
display the list of available remote devices. Mobile device

Make sure you enable developer features in your Open the App in Windows Mobile device and see
device and pair it with your development PC. how our App interacts with Media Controls and plays
Audio in the background.

- Create App Package for MusicPlayer by Right


click MusicPlayer project -> Store -> Create App
Packages…
Raspberry Pi 2
Let us deploy our Music Player app to a Raspberry
- In the popup message. Select No for “Do you want
Pi 2 which is running Windows 10 IoT Core and see
to build packages to upload to the Windows Store”
how the App works in a complete new device family
and click Next.
without any change.

- Choose a folder and click create to create App


Setup your PC by following the Getting Started
Packages (Make sure ARM Architecture is selected)
Instructions here http://bit.ly/1DQVtr3 . Then
download the latest preview version of Windows 10
- Type WinAppDeployCmd install -file
IoT Core from downloads Page http://bit.ly/1GBq9XR
"MusicPlayer_2.0.1.0_arm_Debug.appxbundle" ip

56 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


Setup your Raspberry Pi 2 by following the
instructions here http://bit.ly/1dLQTOp

If everything is setup properly, you will see your


Raspberry Pi 2 listed in Windows IoT Core Watcher.

Windows 10 IoT core can run only one App in


the foreground. To increase the performance, the
raspberry Pi version of the Music Player app can be
Open the Music Player solution in Visual Studio and simplified by removing the background Task and
follow these steps to deploy the App. using MediaElement or playback as shown in the
first part of this series.
- Right click Music Player project and select
Properties
Conclusion
- Click Debug tab and Select Target Device to
The Universal Windows Platform Apps aims at
Remote Machine
changing the way we create apps. Instead of
creating separate apps for different platforms, UWP
- Enter the ip address of your Raspberry Pi2 or click apps would run across all major platforms with
Find to scan for multiple devices and select the minor code changes. With Windows 10, Microsoft
Target device. aims at bringing different platforms - PC, tablets,
phones, XBox, Internet of Things (IoT) together
and we sincerely hope that this platform and
the benefits it brings, will create an attractive
ecosystem for Windows 10 devices

Download the entire source code from GitHub at


bit.ly/dncm21-win10uwp

About the Author


Shoban Kumar is an ex-
Microsoft MVP in SharePoint who
currently works as a SharePoint
Consultant. You can read more
- Change Target platform to ARM about his projects at http://
shobankumar.com. You can
also follow him in Twitter @
- Press F5 to deploy and debug the App or simply shobankr
Right click Music Player Project -> Deploy to deploy
the App and start enjoying your Sound Cloud Music
player in Raspberry Pi 2. Here's a screenshot: shoban kumar

www.dotnetcurry.com/magazine 57
Angular 2
Developer
Preview
These days, front-end JavaScript facing. This is one of the In case you are wondering
frameworks are a trending topic reasons why the Angular about a migration strategy
across the developer community. team has decided to write the from Angular 1 to Angular
Heavy usage of these frameworks next version, Angular 2 from 2, please refer to this link
has made the JavaScript language scratch leveraging the latest - http://angularjs.blogspot.
designers think of making the enhancements of the web. in/2015/08/angular-1-and-
language better, and fit it to the angular-2-coexistence.html
scale at which it is being used
Though Angular 1.x has
these days. The ECMAScript 6
proved to be a good In case you haven't heard of it
specification has brought in a
framework for building rich earlier, Microsoft and Google
significant number of changes to
internet applications (RIA), it are working together to help
the language and the language
was built with older browsers make Angular 2 better. Angular
designers have decided to make
in mind. The framework had to has been using AtScript,
these updates more frequent
build its own module system a superset of Microsoft’s
to keep the language relevant
and a set of abstractions to TypeScript and both these
to the changing landscape of
make its usage easier. By languages have been merged
web development. Browser
leveraging the new features now into TypeScript. Going
vendors are also keeping up
of the web, the framework forward, you will be writing
by progressively implementing
won’t have to define certain Angular 2 applications using
ECMAScript 6 changes over
abstractions, and will TypeScript.
time. [Recommended reading
instead focus on making the
- http://www.dotnetcurry.com/
experience of working on it In this article, we will take a
javascript/1090/ecmascript6-es6-
better in many other ways. look at the core concepts and
new-features ]
Angular 2 still adopts some the basic features of Angular
of the good things from 2.
These changes to the language Angular 1, but at the same
and the web as a whole, makes time, it abandons features
the ecosystem better. The Disclaimer: Angular 2 is still
that complicate things while in alpha. The code snippets
frameworks built on this new writing large applications or,
ecosystem will be able to provide shown in this article and in the
the features that are already supporting sample code may
better ways of solving problems covered by the language.
that the developers are actually not work in the future releases.

58 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


the subtree using immutable objects, are not parsed
Angular 2 Core Concepts until such an event occurs. When the event is raised,
the subtree is checked and the changes are applied
Like Angular 1, Angular 2 (currently in alpha) is on it. The checks will not happen on browser events
built on a set of concepts that are used throughout following this check, unless the event is raised
the framework and they would be used directly or again.
indirectly, while writing applications. Let’s take a
look at them. • Observable Objects: The observable objects
implement a reactive mechanism of notifying the
Change Detection changes. They emit events when the object changes.
Subscribers to these events get notified whenever
the object changes and they can use the new value
At the heart of any front-end web framework to update UI or, perform the next action upon
is the technique used for change detection. receiving the notification.
Angular 2 adds a powerful and much flexible
technique to detect changes on the objects used
Angular 2 understands observable objects. When an
in the application. In Angular 1, the only way
object sends a change notification, the framework
the framework detects changes, is through dirty
checks for changes in the subtree under the node
checking. Whenever digest cycle runs in Angular 1,
containing the component depending on the
the framework checks for changes on all objects
changed object. This subtree won’t be checked for
bound to the view and it applies the changes
any changes until another change event on the
wherever they are needed. The same technique is
same object is raised.
used for any kind of objects. So here we don’t have
a chance to leverage the powers available in objects
- like observables and immutables. Angular 2 opens
this channel by providing a change detection
system that understands the type of object being
used.

In addition, the change detectors in Angular 2


follow a tree structure to detect changes. This
makes the system predictable and it reduces the
time taken to detect changes.
Both immutable objects and observable objects
reduce the number of comparisons to be made
If plain JavaScript objects are used to bind data on while detecting changes. This improves the
the views, Angular has to go through each node and performance of the application.
check for changes on the nodes, on each browser
event. Though it sounds similar to the technique
There is no restriction on usage of libraries for
in Angular 1, the checks happen very fast as the
the two types of objects discussed above. We can
system has to parse a tree in a known order.
use any library according to our convenience. It is
If we use Observables or, Immutable objects also possible to use both immutable objects and
instead of the plain mutable objects, the framework observable objects together in the same application.
understands them and provides better change
detection. Let’s delve further into the details:
We need to tell the framework that the component
uses one of these objects. It can be done using a
• Immutable Objects: As the name itself says, property in the component annotation.
an immutable object cannot be modified as it is
created. A change made in the object re-creates the @Component({
object itself. The re-creation kicks in an event to selector:'my-component',
changeDetection: ON_PUSH
notify user about the change. So the bindings under
})

www.dotnetcurry.com/magazine 59
Angular 2 are more similar to the way DOM appears
Dependency Injection and they provide ways to get into life cycle events
to take better control over the way a directive
Dependency injection (DI) has been a part of typed works. Architecture of the directives in Angular 2
object-oriented languages for quite some time and embraces bindings a lot and hence reduces the
the pattern continues to play an important role need of direct DOM manipulation. Also, we don’t
there. It makes the code testable and maintainable need to deal with different restrict types as well
as usage of the pattern reduces dependency on as with the camel case notation while naming
concrete objects in components of the application. directives; both of these properties are handled by a
Many JavaScript developers, including me, felt single selector property.
happy when we saw DI implemented in the Angular
framework. Without any doubt, it is one of the There are three different types of directives in
reasons behind wide usage of the framework. Angular 2:

Angular 2 continues to use this pattern. It now • Component Directives: Everything in an Angular2
provides us with a simple and yet powerful DI application is a component. The application
container. The DI container in Angular 2 has a starts by bootstrapping a component and other
single API for injecting dependencies and it also components are rendered as children of this
provides ways to control lifecycle of dependencies component. So hypothetically if we take an aerial
and specify the type of dependency to be injected view, an Angular 2 application looks like a tree of
when a type is requested. The DI works in the components. The components are used to define a
same hierarchy in which the components are built. new HTML element. This feature is built using the
Dependencies have to be declared along with techniques introduced in HTML5 web components.
annotations of the components. A dependency If the browser doesn’t support any of the features,
declared on a component can be used either by the the framework emulates them.
same component or by any of the children of the
component. Children components can override the Code of a component includes a class and two
way a dependency is declared in the parent as well. annotations. The following snippet shows structure
of a component written in TypeScript (if you are
Zones not familiar with TypeScript, you may want to check
a basic tutorial on the topic: Hello TypeScript –
After the application starts, we need a process Getting Started):
to keep running behind the scenes that kicks
in the process of change detection so that the @Component({
selector: 'my-component', //Name of
model and the UI are always in sync. Angular 2 the component, it will be used in HTML
includes a library called Zone.js, which helps us bindings: [MyService] //List of
in keeping things always in sync. A zone is an services to be used in the component
execution context that persists across async tasks. or, its children
All operations performed in Angular 2 are carried })
under this context. We don’t need to invoke them or
@View({
attach operations to them. Zones know what kind template: '<div>{{sampleText}}
of operations to be handled in the context. Because </div>', //Template of the component
of zones, we don’t have to take any pain while directives: [] //List of directives
including non-angular UI components in Angular 2. to be used in the component
})

Directives class MyComponentClass{


public sampleText: string;
constructor(private svc: MyService){
Like in Angular 1.x, directives in Angular 2 are used this.sampleText = this.svc.message;
to extend HTML. The directives in }
}

60 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


As we can see, the component is a class decorated introduces a different syntax for data binding.
with the annotations Component and View. An object Public properties of the component class can be
of this class is the view model for the component. bound to any element on the view. For example,
Any public property defined in this class can be following snippet binds the property heading to an
used to bind data in the component’s template. h1 element:

• Decorator Directives: A decorator is the simplest <h1>{{heading}}</h1>


kind of directive. It is used to extend behavior of
an HTML element or an existing component. This The public properties can be assigned as value to
directive doesn’t make a lot of impact on the view, any of the properties as well. The properties can be
but helps in achieving certain small yet important bound in two ways:
functionalities on the page. A decorator directive
is a class with the Directive applied on it. The <span [title]=”myTitle”> Some text in
following snippet shows an example of a decorator the span </span>
directive:
Or,
@Directive({
selector:'[my-decorator]', <span bind-title=”myTitle”> Some text in
host: { the span </span>
'(mouseover)': 'myFunction()'
} The bind-title attribute in the above snippet is not
}) a decorator directive, the prefix bind is a convention
class MyDecoratorClass{
and it is an alternative syntax to the square bracket
//class definition
} [attribname] syntax used earlier. The bind- prefix
can be used with any valid HTML attribute to bind
If you observe this snippet, the directive interacts the property with a value on the view model.
with the host element through configuration. And
if we use this feature effectively, we can avoid Similarly, public methods defined in the component
performing direct DOM manipulations in the class can be used to handle events.
component. Such behavior makes the code easy to
port to non-browser based applications. <button (click)=”clicked()”>Click
Here!</button>
• Directives with ViewContainer: The directives
Or,
that use a ViewContainerRef object can take control
over the content of the element on which they
are applied. These directives can be used when <button on-click=”clicked()”>Click
template of the view has to be shown/hidden Here!</button>
based on a condition, to iterate over, or to tweak the
content based on a scenario. The directives like Angular 2 doesn’t have direct support for two-way
ng-for and ng-if fall into this category. binding. All property binders are one-way. It has a
work around to support two-way binding. Following
is the syntax:
Bindings and Templates
<input type=”text” [(ng-model)]=”name”
Like every front-end framework, Angular 2 has a very />
good support for binding. As already mentioned,
The two-way binding in Angular 2 is a combination
view-model for any component is an object of its
of property binding and event binding. Value of the
class. Public properties and methods of the classes
property is bound to text of the textbox and any
can be used to show data, handle events and handle
change in the text raises an event to update the
properties of the HTML elements. The framework
model. In fact, the above snippet is the shorter form

www.dotnetcurry.com/magazine 61
of the following snippet: in this article is to show how Angular 2 code can be
written using both TypeScript and ES5.
<input type=”text” [ng-model]=”name”
(ng-model)=”name=$event” />
Music player using EcmaScript 5
(ES5)
Services
The Angular 2 framework has two different versions
Angular 2 doesn’t have the concept of services.
of its JavaScript file, one to be used with ES6 or,
Anything other than directives are simple classes.
TypeScript and the second for ES5. If you visit
Good thing is, we can apply dependency injection
Angular’s code library for current version (alpha 37),
on these classes and these classes can be injected
you will find multiple versions available for each
into any directives. We can consider any plain
file. The Angular 2 core framework’s ES5 version is
simple class as a service. The following snippet
angular2.sfx.dev.js and ES6 version is
shows a service and its usage in a component using
angular2.dev.js. For the ES5 example, we will use
TypeScript:
angular2.sfx.dev.js.
class Message{
greeting: string; After including this file on the page, we can start
constructor(){ writing some JavaScript. At first, let’s create a service
this.greeting = "A sample message"; to store data. It can be any constructor function
} with some public fields. In the component, we will
} be showing the current song being played and
@Component({ next and previous buttons with tooltips showing
selector: 'show-message', the corresponding songs. We just need three fields
bindings: [Message] assigned in the constructor function.
})
@View({ function MusicPlayerInfo() {
template: '<div>{{message}}</div>' this.nowPlaying = "Yaad kiya dil ne";
}) this.next = "Hosh walo ko khabar";
class ShowMessage{ this.prev = "Hotho se chulo tum";
message: string; }
constructor(messageSvc: Message){
this.message = messageSvc.greeting; To show the next and previous songs, we need
}
} to create a directive that uses data on the above
service and displays name of the song in a tooltip.
The Angular 2 library exposes an API that makes the
Let’s build a component code of directive look very close to the ES6 syntax.
As already discussed, we need to define a class and
Now that we had a tour around some new features apply the directive decorator to make it a directive.
of Angular 2, let’s build a simple component. ES5 version defines the methods Directive and Class
An Angular 2 application can be written using to make this task easier. The following snippet
ECMAScript 5, ECMAScript 6 (ECMAScript 2015) or, shows code of the directive:
TypeScript. The code written in ES6 and TypeScript
var SongTip = ng.Directive({
is almost similar except that TypeScript would
selector: '[song-tip]',
have support for types. We will build a simple properties: [
music player component using ES5 and then using 'label: song-tip'
TypeScript. ],
host: {
'(mouseover)': 'show()',
Note: Instead of writing the component in both
'[title]': 'title'
TypeScript and ES5, I could have used a TypeScript }
compiler to generate ES5 code. However my intention })

62 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


.Class({ Following is the mark up in the musicPlayer.html
constructor: [MusicPlayerInfo, file:
function (info) {
this.info = info; <div class="col-sm-6">
}], <div class="col-sm-3 text-center"><span
show: function () { class="glyphicon glyphicon-step-
this.title = this.info[this.label]; backward" song-tip="prev"></span></div>
}
}); <div class="col-sm-6 text-center"><span
class="glyphicon glyphicon-play">
In the above snippet: </span><br/>{{nowPlaying}}</div>

<div class="col-sm-3 text-center"><span


• The properties option in the directive decorator is class="glyphicon glyphicon-step-
used to add properties to instance of the directive forward" song-tip="next"></span>
class with value assigned to a field on the element. </div></div>
Here, a field named label is added to the class that <div class="col-sm-6"></div>
would hold value assigned to song-tip
A few things to observe in the above snippet are:
• The host option is used to interact with the host
element of the directive. Here we are handling the • The bindings option in component decoration
mouseover event and setting title to the element says the component depends on MusicPlayerInfo.
using a method and a property on the directive That means it can be injected in the component and
object any of its children components or, directives

• Constructor defined in the class depends on • The directives option on the view says the
the service MusicPlayerInfo. So the dependency component will use the directive SongTip
is specified in the annotation. We haven’t bound
this dependency yet, we will do that in the next • The field nowPlaying created in the constructor is
component used in template of the component

We need to have a component element to show Let’s create another component MusicPlayerHost
play, current and previous buttons. We will call to host the above component and this component
this component MusicPlayer. The previous and will be used for bootstrapping the application. The
next buttons will have the SongTip directive following is the snippet showing the code of the
applied. It would use the field nowPlaying from component:
the MusicPlayerInfo service to show the currently
playing track. The following snippet shows code of var MusicPlayerHost = ng.
Component({
the component: selector: 'music-player-host'
})
var MusicPlayer = ng.Component({ .View({
selector: 'music-player', template: '<h2>{{message}}
bindings: [MusicPlayerInfo] </h2><music-player></music-player>',
}) directives: [MusicPlayer]
.View({ })
templateUrl: 'templates/musicPlayer. .Class({
html',directives: [SongTip] constructor: function () {
}) this.message = "My music player";
.Class({ }
constructor: [MusicPlayerInfo, });
function (musicInfo) {
this.nowPlaying = musicInfo. As the Angular 2 application has to start with a
nowPlaying;
}] }); component, let’s bootstrap the application using the

www.dotnetcurry.com/magazine 63
MusicPlayerHost component. The bootstrap process typescript: ts
has to begin after the DOM content is loaded, so we });
need to add a listener to the DOMContentLoaded
event to bootstrap the application. return gulp.src(['typings/**/**.ts',
'typescript/*.ts'])
.pipe(sourcemaps.init())
document. .pipe(gts(tsProject))
addEventListener('DOMContentLoaded', .pipe(sourcemaps.write('../maps', {
function () { includeContent: false, sourceRoot: '/
ng.bootstrap(MusicPlayerHost); typescript' })
}); .pipe(gulp.dest('js'));
});
Music Player using TypeScript
This task copies all of the transpiled files into the
js folder. The HTML file rendering the application
Setting up the environment with TypeScript loads the helper libraries and then loads the main
needs some efforts. The TypeScript code has to be module of the application using SystemJS, which in
converted to JavaScript before the application is turn loads all other modules.
loaded in the browser. The process of converting
TypeScript to JavaScript is called transpilation. <script src="\node_modules\traceur\bin\
The word transpilation is derived from the words traceur-runtime.js"></script>
translation and compilation. In addition, we should
have a module loader to load the transpiled <script src="\node_modules\systemjs\
modules along with the modules exposed by dist\system.src.js"></script>
Angular 2. The demo code contains the following
NPM packages to fill these gaps: <script>
System.config({
defaultJSExtensions: true
• typescript, gulp and gulp-typescript to transpile });
TypeScript </script>

• systemjs to load modules <script src="\node_modules\angular2\


bundles\angular2.dev.js"></script>
• traceur to make the browser understand Angular <script>
2’s annotations System.import('/js/bootstrap');
</script>
Note: We are using Gulp to perform the task of
transpilation. If you are not familiar with Gulp, you may All of the code that we wrote in the previous
read the section on Gulp in the article Using Grunt, section will take a different form with
Gulp and Bower in Visual Studio 2013 and 2015 TypeScript classes. The following is the class for
MusicPlayerInfo service:
The typescript task defined in gulpfile.js transpiles
export class MusicPlayerInfo{
the files and generates sourcemaps. This is shown
nowPlaying: string;
below: next: string;
prev: string;
var gulp = require('gulp'),
gts = require('gulp-typescript'), constructor(){
ts = require('typescript'), this.nowPlaying = "Yaad kiya dil
sourcemaps = require('gulp- ne";
sourcemaps'); this.next = "Hosh walo ko khabar";
this.prev = "Hotho se chulo tum";
gulp.task('typescript', function(){ }
var tsProject = gts. }
createProject('tsconfig.json', {

64 DNC MAGAZINE Issue 21 (Nov-Dec 2015)


The SongTip directive needs the Directive annotation import {Component, Directive, View} from
and the service MusicPlayerInfo to be imported 'angular2/angular2';
into the module and then use them in the code. import {MusicPlayerInfo} from './
Annotations in Angular 2 are decorators (a feature MusicPlayerInfo';
import {SongTip} from './SongTip';
to be released in ES7, and is already implemented
by TypeScript) with metadata information. As @Component({
TypeScript understands decorators but not selector:'music-player'
annotations, as they are not a part of the standard })
language, we need to use the traceur compiler @View({
(which is already included) to parse them on the templateUrl:'templates/musicPlayer.
html',
browser. Following snippet shows the code of this directives:[SongTip]
directive: })
export class MusicPlayer{
import {Directive} from 'angular2/ nowPlaying: string;
angular2';
constructor(info: MusicPlayerInfo){
import {MusicPlayerInfo} from './ this.nowPlaying = info.nowPlaying;
MusicPlayerInfo'; }
}
@Directive({
selector:'[song-tip]', The MusicPlayerHost component is straightforward.
properties: [ It uses the above component, so it has to be
'label: song-tip'
specified in directives.
],
host: {
'(mouseover)': 'show()', import {bootstrap, Component, View} from
'[title]':'title' 'angular2/angular2';
} import {MusicPlayerInfo} from './
}) MusicPlayerInfo';
import {SongTip} from './SongTip';
export class SongTip{ import {MusicPlayer} from './
title: string; MusicPlayer';
label: string;
constructor(private musicPlayerInfo: @Component({
MusicPlayerInfo){} selector:'music-player-host',
bindings: [MusicPlayerInfo]
show(){ })
this.title = this.
musicPlayerInfo[this.label]; @View({
} template: '<h2>{{message}}</h2><music-
} player></music-player>',
directives:[MusicPlayer]
Notice the constructor in the above class. It accepts })
a parameter of type MusicPlayerInfo and we don’t
class MusicPlayerHost{
need to add anything in addition for dependency
message: string;
injection, as the type specification in the constructor constructor(){
itself is used for injecting the dependency. this.message = "My music player";
}
Similarly, the MusicPlayer component needs the }
annotations Component and View from Angular’s
To bootstrap the application, the above component
core modules and MusicPlayerInfo from the current
can be passed to the bootstrap function.
folder. The annotations Component and View have
the same responsibilities as they had in previous
section; they just appear a bit different. bootstrap(MusicPlayerHost);

www.dotnetcurry.com/magazine 65
Conclusion

Angular 2 is written from ground-up using latest


features available in the web ecosystem and it
brings several significant improvements over the
framework’s older version. While it retires a number
of Angular 1 features, it also adopts a number of
core concepts and principles from older version
of the framework. After collaborating with the
TypeScript team at Microsoft, both the teams are
working really hard to create a great framework
and they are also working with TC39 team to make
JavaScript a better language. Let’s try it, explore
and provide feedback to the core team on making it
better!

Download the entire source code from GitHub at


bit.ly/dncm21-angular2features

About the Author

Rabi Kiran (a.k.a. Ravi Kiran) is a


developer working on Microsoft
Technologies at Hyderabad. These
days, he is spending his time on
JavaScript frameworks like AngularJS,
latest updates to JavaScript in ES6
and ES7, Web Components,
Node.js and also on several Microsoft
technologies including ASP.NET
5, SignalR and C#. He is an active

ravi kiran blogger, an author at SitePoint and


at DotNetCurry. He is rewarded
with Microsoft MVP (ASP.NET/IIS)
and DZone MVB awards for his
contribution to the community

66 DNC MAGAZINE Issue 21 (Nov-Dec 2015)

You might also like