DNCMag Issue21
DNCMag Issue21
Upgrading Existing
06 C# Code to C# 6.0
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.
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));
}
// 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.
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"
};
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
Conclusion:
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.
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.
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
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:
Summary
www.dotnetcurry.com/magazine 19
DESKTOPS IN THE CLOUD
RUN DESKTOP APPLICATIONS
IN THE CLOUD USING
AZURE REMOTE APPS
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.
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)
4. Configure application and create template image Click Create button to proceed with storage account
(in source code) creation.
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.
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.
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 –
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.
www.dotnetcurry.com/magazine 31
To enable drive redirection, run the following
command –
Set-AzureRemoteAppCollection -CollectionName
"dnccollection" -CustomRdpProperty
"drivestoredirect:s:*”
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
Conclusion
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.
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.
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
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.
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
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:
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.
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.
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:
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:
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!
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.
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/ {
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 =
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.
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.
}
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.
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.
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
})
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 })
• 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>
www.dotnetcurry.com/magazine 65
Conclusion