Pages

Tuesday, June 16, 2015

Introduction to TypeScript for (Xrm) Developers

Hey!  It’s finally here!  The long-awaited article companion to my xRMVirtual presentation.  If you haven’t seen the video, then I invite you to do so.  If you have, then I apologize for wandering, at times, and trying to squeeze too much into too little a timeframe.  I ended up repeating the content to a different group of colleagues, and I went about 90 minutes—spending more time in the live demonstration, than in much of the content I presented initially.  That said, I would like to provide a repeat of the demonstration material in a separate video in the near future.

So, parting with the final ado:

Table of Contents

What Is TypeScript?
EcmaScript Compatibility
The TypeScript Experience
The TypeScript Experience… as an Xrm Developer
What Do You Need to Get Started?
I Can Haz Ready?
Using the XRM Definitions
TypeScript’s Xrm API Documentation
Now You Haz Ready

What Is TypeScript?

The purpose of TypeScript is to bring meaningful static typing, application-scale architecture, and object-oriented design directly to JavaScript; unlike Dart which is not compatible with JavaScript. It's origin at Microsoft's C# development team, imparts some heritage with regard to the behaviors of classes, interfaces, and inheritance.

TypeScript is an open-source language that is a strict superset of JavaScript.  It "transcompiles" into raw JavaScript. For the jargon-watchers:

  1. Superset - All valid JavaScript is valid TypeScript; TypeScript adds to JavaScript without taking away.
  2. Transcompiles - "Source-to-source". Mostly this is accomplished by removing TS markup, however some language constructs undergo a more nuanced conversion.

A TypeScript file has the extension .ts, and will build into an identically named, JavaScript file with the extension .js (without customizing compiler commands).  The best resource for learning about everything TypeScript can do, comes from its language specification.

What Does that Mean?

TypeScript should be an approachable language for developers that are more comfortable with object-oriented development and architecture. It expands all of the wibbly-wobbly, typey-wipey ambiguity of JavaScript into a framework of variable rigidity. TypeScript kindly steps out of the way when you need it to.

EcmaScript Compatibility

In the web-development world, EcmaScript is king, and TypeScript does well to bow to it.

"ECMAScript is the scripting language standardized by Ecma International in the ECMA-262 specification and ISO/IEC 16262. The language is widely used for client-side scripting on the Web, in the form of several well-known implementations such as JavaScript, JScript and ActionScript." --Wikipedia

TypeScript's stated direction is to provide feature-parity with EcmaScript 6. Indeed, many of TypeScript 1.4's current features, and the coming 1.5 update will bring the language very close to party with the current specification for EcmaScript 6.

However, you might be surprised to discover that by default, it builds down into EcmaScript 3, which supports a very broad range of browsers (going back to at least IE6, but if you know somebody that is still using IE6, please thaw out their cryo-chamber). Some features require newer versions, such as getters and setters, which require ES5. Most other features are build down into a syntax that works in the older language, such as classes or template strings, which are native to ES6, but built into ES3/5 in a very specific manner so as to allow the ES6 syntax/style to be leveraged for "older" platforms.

The TypeScript Experience

Starting with Visual Studio 2013, TypeScript became a first-class language in Microsoft's development ecosystem. While the design-time experience lags in some ways, compared to C# development, it is markedly better than JavaScript in many others. A class/module and member navigation dropdown doesn't seem like a big deal, but compared to the native JS authoring experience, it's a miracle.  (Although Visual Studio 2015 finally introduces this!)image

Type inference also helps keep the requisite TypeScript syntax to a bare minimum, and where it is most useful.  However, you can expect it to nag at you as you design, doing so with real-time compiler validation.  Thankfully, it also offers great IntelliSense support to sort out type issues on-the-fly.

image

Code documentation is formulated in JSDoc, which is more widely used by web-developers, and does break away from XML documentation common to Visual Studio. (I use Atomineer Pro to help generate documentation. It's inexpensive, and offers TypeScript support.)

Most of your time in TypeScript, though, is thinking about classes, modules, interfaces, and… well… types. JavaScript developers don't always think in object-oriented terms, so that can help them understand the advantage OO architecture has for scalability, modularity, and interoperability.

The TypeScript Experience… as an Xrm Developer

Having immediate feedback at design-time for relatively simple syntax costs, helps me build applications that are modular, stable, and scalable. Reducing the number of pseudo-type validations being performed at runtime, on parameters and method returns, requires a measure of faith in TypeScript's results, but simplifies JavaScript code and improves performance overhead. However, if you intend to build something for public consumption, then performing runtime pseudo-type checks is still advisable. However, I imagine a day where-in we have native TS, and JS versions of libraries that allow us to squeeze incredible performance out of JavaScript.

So, what are you supposed to do with an existing JavaScript API that has no TypeScript counterpart? This was a problem that many of us early TypeScript adopters tried to solve, and TypeScript's way of solving it is with hard-earned type definitions that effectively describe the entire library's types, without all the code stuff.

These are called "TypeScript Definition Files", and carry the special extension .d.ts. This approach is effective, although not always perfect, and is often at the mercy of the crowd--rather than the library's original author. However, there are projects that are good about self-made definitions, and I'd like to give a shout-out to Telerik's Kendo UI framework for being one such example.

There are a handful of Dynamics CRM definition files for TypeScript available, and I hope you'll choose to use mine--which I will demonstrate for you today. My project provides full documentation and type definitions for the Xrm JavaScript API for CRM 2013 and 2015 (with separate definition files for 7.0 and 7.1).  It has also been accepted into the DefinitelyTyped repository.

Sidebar:  DefinitelyTyped is the premier resource for TypeScript developers. It contains a staggering repository of type definitions for nearly every JavaScript API framework that is common among modern web developers. Each library is packaged and made available both on NuGet and a special "TypeScript Definition Manager" (for NuGet-less environments).

What Do You Need to Get Started?

Software

Wetware

  • Constructors and Objects:  http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/  You might be surprised at what you have been taking for granted, and this is a good guide for understanding the output of a compiled TypeScript project.
  • Closures and Scopes:  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures  Learn how to use anonymous objects and methods to interlink scopes.  This is useful for leveraging TypeScript lambda expressions, which preserves potentially ambiguous context variables in the generated JavaScript.  Classes, modules, and mix-ins between them, all utilize carefully architected closures.
  • this (literally): http://www.2ality.com/2014/05/this.html  What this really means, and why it can put your code in jeopardy.  Thankfully, TypeScript uses a this redirect to help, but when writing TypeScript code, that redirect is called this inside class definitions.
  • Truthiness:  http://www.sitepoint.com/javascript-truthy-falsy/  It’s essential to understand the primitives and how they cast into Boolean evaluation, and when the use of strict equality (===, !==) can be abandoned.  Hint: only in circumstantially deliberate ways.
  • instanceof:   https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof  The diamond in the rough of operators, this poor sob used to languish in abandonment in older JavaScript-native class and module frameworks, deferring many to runtime type validation via a method (e.g. Object.instanceOf()).  TypeScript allows you to comfortably validate an instance of a class or an ancestor class with this operator, thanks to the transcompiled output of class constructors.  ES6 offers JavaScript the same power, so it can be considered best practice to use it.
  • typeofhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof  Did you know the expression typeof null; evaluates to “object”?  It surprised me.  Probably a good idea to keep this reference handy.

I Can Haz Ready?

Yes!  You’re ready to get started in the world of TypeScript development.  Just crank open your TypeScript-enabled IDE of choice, and keep the language reference guide handy, and you’ll be set to develop in TypeScript.

But Wait…

If you’re developing web resources in Dynamics CRM, and you would like some IntelliSense for the Xrm.Page context, or you would like the whole Xrm API for form-related scripting needs, then I encourage you to install the Xrm definitions files from DefinitelyTyped.

NuGet Console:  Install-Package xrm.TypeScript.DefinitelyTyped

Using the XRM Definitions

At first download, several definitions will be available:  CRM 2013 (6), CRM 2015 (7.0), and CRM 2015 Service Update 1 (Current), ClientGlobalContext, and Parature.  Because DefinitelyTyped only accepts definitions that are vetted with their build-testing framework, these files rely on <reference> decorators in file comment headers.

At compile time, a TypeScript project in Visual Studio will instead include all files within the project (by default).  This causes compiler errors, as each version of the main definition file conflicts with the definitions of the others.  To get around this problem, simply exclude the definitions which are not appropriate for the project:

image

Now, for best practice, even though Visual Studio will handily incorporate IntelliSense for Xrm throughout your project files, please include the appropriate <reference> header:

image

This assures the portability of your TypeScript code to other development environments, and makes for a good indicator of the runtime requirements your code will have.

TypeScript’s Xrm API Documentation

For TypeScript, the Xrm API has been enhanced with generics, interfaces, enumerations, and type unions.  No additional functionality has been provided, and due to the nature of a definition file, no code will be produced to support it.  Instead, these enhancements help encapsulate functionality and accurately describe the intent and behavior of the code at runtime.

Robust documentation has been provided to the TypeScript definition files, largely borrowed from Microsoft’s own documentation.  This provides a remarkable IntelliSense experience.  However, with TypeDoc, I’ve created a navigable documentation page to help with understanding it:

https://6ix4our.github.io/Xrm-TypeScript-Documentation/index.html

Now You Haz Ready

There is a tests file in the repository that should help demonstrate some of the basic concepts employed in the API definition.  In all, I find that the definition file makes it easier to develop by reducing the amount of time spent looking at the Microsoft API documentation.  It does this with stronger typing, which properly sets the code’s expectations, given a little more forward effort on my part to accurately provide type decorations.  I encourage you to examine it in Visual Studio, and play with it.

As always, I’m welcome to suggestions and pull requests.  So, if you have an improvement, or some better test scenarios to share with the community, I welcome them!

Cheers!

Thursday, April 2, 2015

Debugging Dynamics CRM for Outlook

I had a recent adventure with a Kendo UI project that took me into the recesses of a place I have very skillfully avoided for 7 lucky years: debugging JavaScript in the CRM for Outlook client.  The problem jumped out at me at the worst possible moment: Go Live.  Apparently the testers hadn’t thought to use the Outlook client, even though a majority of users would.  I number myself among them.

This lead me to discover a quaint little bug in the CRM for Outlook client: when you use JQuery to attach to multiple mouse events (“mousedown”, “mouseup”, and “click”) in an HTML Web Resource, only the first one in the event sequence gets its handlers fired.  The rest of the sequence does not complete.

“Wait, what?”  That’s what I said, too.  I’m going to recount the tale here, in case anyone else runs into this bug, but I will return to the process of debugging JavaScript in Outlook.

So, it works like this: when you click on a mouse button, there are 3 distinct events sent through the browser’s runtime, in order:

  1. mousedown  “The button is pressed down.”
  2. mouseup  “The button has been released.”
  3. click  “The button was pressed and released.”

The way this bug manifests, is when more than one of those events is being watched—at least by jQuery, anyway.  (I haven’t taken the time to see if browser-native event handlers are not affected in this way.)  By attaching a handler to both the “mousedown” and “click” events, we expect that a click will trigger that handler twice. 

It does; in every other browser, but not within the Outlook client.  This is actually incredibly easy to test:

<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#clickable").on("mousedown", function() { alert("Mouse is down.");});
$("#clickable").on("mouseup", function() { alert("Mouse is up.");});
$("#clickable").on("click", function() { alert("Mouse was clicked.");});
});
</script>
</head>
<body>
<span id="clickable">Click on me to see the event pipeline.</span>
</body>
</html>

This means that developers may need to find creative solutions to enable or support richer HTML interfaces from within Outlook.  Thankfully, the client-side context has a helpful getClient() method.

With that behind us…

So, the process of debugging Dynamics CRM for Outlook hasn’t changed the whole time I’ve been avoiding it, and the process is actually very simple: you debug with Visual Studio.

First, allow Visual Studio to do the dirty work by deselecting “Disable script debugging (Other)” from the Outlook machine’s Internet Options.

image

Then, launch Outlook and Visual Studio.  Do not attach to Outlook’s main process.  Find the page you want to debug, and attach Visual Studio to the instance of Microsoft.Crm.Application.Outlook.WebFormsHost.exe matching the page you’re viewing.  Each new window gets its own host process, so look carefully.

image_thumb[50]

After that, you should be able to summon the debugger with a simple “debugger;” statement.  What you’ll probably miss most, like I did, is a nice JavaScript console, and a DOM Explorer, like those found in the debugging tools of most browsers.

Then, when you make changes to your HTML or JavaScript, you’ll run into CRM for Outlook’s quirky, bi-layered cache.  The steps to clear the cache are as follows:

  1. Launch Internet Options from the Control Panel.  You cannot rely on the Internet Options launched from Internet Explorer’s menu—it doesn’t reach into the client’s cache, which I speculate is maintained in a phantom profile.
  2. Delete browsing history:
    image
  3. Launch the Diagnostics utility, which was installed with the CRM for Outlook connector.  It can be found in the Start Menu.  Repair your installation if you cannot find it.
  4. Under “Advanced Troubleshooting”, click to “Delete Temporary Microsoft Dynamics CRM Client Files”.
    image

For JavaScript changes, this is enough—simply hit F5 and the page will reload with your changes.  For HTML resources, you will first need to close all CRM windows displaying the page, and then use the process above.

That’s really all there is to it.  I decided to write it all up here, because this information wasn’t easy to come by, and involved some trial and error.  Hope it helps!

Tuesday, August 26, 2014

A CRM Book and eXtremeCRM

I’ve undergone a change of employers, for both personal and professional reasons, but hope that will serve as a catalyst to reconnect with the Dynamics CRM community—with whom I’ve grown too distant for comfort.  Though I’m never more than a stone’s throw from you all, I feel that the lack of regular communication from me has alienated my audience.  While I’ve been growing and learning, I’ve been amassing a collection of knowledge and experience that I want to pass along—and I’d like to commit to doing so through this blog.

However, while all these cards are coming together in the next few weeks, I’ll simply offer some filler.  For those who follow me on twitter, news of a new book with my name on it is currently on the shelves.  The CRM 2013 Quickstart guide is a new work, intended for the intermediate and advanced Dynamics CRM users.  In particular, my contribution is the chapter “Developers, Developers, Developers” at the end.

The material in this book is up-to-date, and is an experienced look into the important differences between CRM 2013 and previous versions.  The digital version is available both on Amazon and through our publisher’s site:  http://www.crm2013quickstart.com/Buy/Discount

Finally, I’ll be attending eXtremeCRM in Las Vegas, Oct. 5th – 8th.  I’m not pegged for any presentations, but I’ll be attending roundtables where I’m welcome.  What I’m looking forward to, is the Innovation Challenge on the Sunday prior to the event.  Last year, I built a tool called “RedHanded” which was a light-weight, use-tracking feature, wholly contained inside CRM.  This year, I’m planning to build… oh, well, I guess you’ll have to be there to find out.  :)