tag:blogger.com,1999:blog-52424980213524714512024-02-20T02:13:42.650-07:00CRM Entropy - A Microsoft Dynamics CRM BlogTales of a Microsoft Dynamics CRM DeveloperDave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.comBlogger91125tag:blogger.com,1999:blog-5242498021352471451.post-39768968153208481722015-06-16T03:42:00.001-06:002015-06-16T12:50:07.533-06:00Introduction to TypeScript for (Xrm) Developers<p>Hey! It’s finally here! The long-awaited article companion to my <a href="http://www.xrmvirtual.com/events/david-berry-presents-an-introduction-to-typescript" target="_blank">xRMVirtual presentation</a>. 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.</p> <p>So, parting with the final ado:</p> <table cellspacing="0" cellpadding="2" width="400" border="0"> <tbody> <tr> <td valign="top" width="398"> <h3 align="center">Table of Contents</h3></td></tr> <tr> <td valign="top" width="398"><a href="#section1">What Is TypeScript?</a></td></tr> <tr> <td valign="top" width="398"><a href="#section2">EcmaScript Compatibility</a></td></tr> <tr> <td valign="top" width="398"><a href="#section3">The TypeScript Experience</a></td></tr> <tr> <td valign="top" width="398"><a href="#section4">The TypeScript Experience… as an Xrm Developer</a></td></tr> <tr> <td valign="top" width="398"><a href="#section5">What Do You Need to Get Started?</a></td></tr> <tr> <td valign="top" width="398"><a href="#section6">I Can Haz Ready?</a></td></tr> <tr> <td valign="top" width="398"><a href="#section7">Using the XRM Definitions</a></td></tr> <tr> <td valign="top" width="398"><a href="#section8">TypeScript’s Xrm API Documentation</a></td></tr> <tr> <td valign="top" width="398"><a href="#section9">Now You Haz Ready</a></td></tr></tbody></table> <h1><a name="section1">What Is TypeScript?</a></h1> <p>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.</p> <p>TypeScript is an open-source language that is a strict superset of JavaScript. It "transcompiles" into raw JavaScript. For the jargon-watchers: <ol> <li><em>Superset</em> - All valid JavaScript is valid TypeScript; TypeScript adds to JavaScript without taking away. <li><em>Transcompiles</em> - "Source-to-source". Mostly this is accomplished by removing TS markup, however some language constructs undergo a more nuanced conversion. </li></ol> <p>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 <a href="http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf" target="_blank">its language specification</a>. <h3>What Does that Mean?</h3> <p>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. <h1><a name="section2">EcmaScript Compatibility</a></h1> <p>In the web-development world, EcmaScript is king, and TypeScript does well to bow to it.</p> <blockquote> <p>"<em>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.</em>" --Wikipedia</p></blockquote> <p>TypeScript's stated direction is to provide feature-parity with EcmaScript 6. Indeed, many of TypeScript 1.4's current features, and <a href="https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript" target="_blank">the coming 1.5 update</a> will bring the language very close to party with the current specification for EcmaScript 6. <p>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. <h1><a name="section3">The TypeScript Experience</a></h1> <p>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. (<a href="http://blogs.msdn.com/b/visualstudio/archive/2015/06/10/javascript-editor-improvements-in-visual-studio-2015.aspx" target="_blank">Although Visual Studio 2015 finally introduces this!</a>)<a href="http://lh3.googleusercontent.com/-SPysSaAX2DQ/VX_vc6ekTJI/AAAAAAAAAwg/j_5aEY76dYk/s1600-h/image%25255B19%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.googleusercontent.com/-vjz-ggumD4I/VX_vdov8uOI/AAAAAAAAAwo/-PXOJoYtlk8/image_thumb%25255B13%25255D.png?imgmax=800" width="566" height="281"></a></p> <p>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.</p> <p><a href="http://lh3.googleusercontent.com/-UtOdOlM34As/VX_veCWzGDI/AAAAAAAAAws/DOlUhLB-lNY/s1600-h/image%25255B18%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.googleusercontent.com/-p-rKUIb8cXU/VX_vebIwV6I/AAAAAAAAAw0/8NioyAMzxZs/image_thumb%25255B12%25255D.png?imgmax=800" width="507" height="78"></a></p> <p>Code documentation is formulated in <a href="http://usejsdoc.org/" target="_blank">JSDoc</a>, which is more widely used by web-developers, and does break away from XML documentation common to Visual Studio. (I use <a href="http://www.atomineerutils.com/" target="_blank">Atomineer Pro</a> to help generate documentation. It's inexpensive, and offers TypeScript support.)</p> <p>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. <h1><a name="section4">The TypeScript Experience… as an Xrm Developer</a></h1> <p>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 <a href="https://angular.io/docs/js/latest/quickstart.html" target="_blank">we have native TS, and JS versions of libraries</a> that allow us to squeeze incredible performance out of JavaScript. <p>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. <p>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 <a href="http://docs.telerik.com/kendo-ui/typescript" target="_blank">Telerik's Kendo UI framework</a> for being one such example. <p>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). <a href="https://github.com/borisyankov/DefinitelyTyped/tree/master/xrm" target="_blank">It has also been accepted into the DefinitelyTyped repository</a>. <blockquote> <p>Sidebar: <a href="http://definitelytyped.org/" target="_blank">DefinitelyTyped</a><em></em><em> is the premier resource for TypeScript developers. It contains a staggering repository of type definitions for </em><a href="https://github.com/borisyankov/DefinitelyTyped/blob/master/CONTRIBUTORS.md" target="_blank">nearly every JavaScript API framework</a><em></em><em> 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).</em></p></blockquote> <h1><a name="section5">What Do You Need to Get Started?</a></h1> <h2>Software</h2> <ul> <li>Visual Studio 2013 Update 2 (or later), Sublime Text, Eclipse <li>TypeScript 1.5: <a href="http://www.typescriptlang.org/#Download" target="_blank">http://www.typescriptlang.org/#Download</a> <li>NuGet: <a href="http://docs.nuget.org/consume/installing-nuget" target="_blank">http://docs.nuget.org/consume/installing-nuget</a>,<br>or TypeScript Definition Manager (Node Package Manager): <a title="https://github.com/Definitelytyped/tsd#install" href="https://github.com/Definitelytyped/tsd#install" target="_blank">https://github.com/Definitelytyped/tsd#install</a> <li>Gulp: <a title="http://gulpjs.com/" href="http://gulpjs.com/" target="_blank">http://gulpjs.com/</a> If you wanna get freaky amazing.</li></ul> <h2>Wetware</h2> <ul> <li>Constructors and Objects: <a href="http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/" target="_blank">http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/</a> 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. <li>Closures and Scopes: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures</a> 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. <li><em>this </em>(literally): <em></em><a href="http://www.2ality.com/2014/05/this.html" target="_blank">http://www.2ality.com/2014/05/this.html</a> What <em>this</em> really means, and why it can put your code in jeopardy. Thankfully, TypeScript uses a <em>this</em> redirect to help, but when writing TypeScript code, that redirect is called <em>this </em>inside class definitions. <li>Truthiness: <a href="http://www.sitepoint.com/javascript-truthy-falsy/" target="_blank">http://www.sitepoint.com/javascript-truthy-falsy</a><a href="http://www.sitepoint.com/javascript-truthy-falsy/">/</a></a> 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. <li><em>instanceof</em>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof</a> 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. <em>Object.instanceOf()</em>). 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 <em>best practice</em> to use it. <li><em>typeof</em>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof</a> Did you know the expression <em>typeof null;</em> evaluates to “object”? It surprised me. Probably a good idea to keep this reference handy.</li></ul> <h1><a name="section6">I Can Haz Ready?</a></h1> <p>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.</p> <h3>But Wait…</h3> <p>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 <a href="https://github.com/borisyankov/DefinitelyTyped/tree/master/xrm" target="_blank">the Xrm definitions files from DefinitelyTyped</a>.</p> <blockquote> <p>NuGet Console: <code>Install-Package xrm.TypeScript.DefinitelyTyped </code></p></blockquote> <h1><a name="section7">Using the XRM Definitions</a></h1> <p>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 <em><reference></em> decorators in file comment headers.</p> <p>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:</p> <p><a href="http://lh3.googleusercontent.com/-762smMZtu9M/VX_vexkTQVI/AAAAAAAAAw8/onvwT8c_dT0/s1600-h/image%25255B16%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.googleusercontent.com/-XjMbvocF4Ss/VX_vfE57IFI/AAAAAAAAAxE/t01FobDJwfc/image_thumb%25255B10%25255D.png?imgmax=800" width="355" height="378"></a></p> <p>Now, for best practice, even though Visual Studio will handily incorporate IntelliSense for Xrm throughout your project files, please include the appropriate <em><reference></em> header:</p> <p><a href="http://lh3.googleusercontent.com/-8pO-zQRr6Pw/VX_vfe4iD_I/AAAAAAAAAxM/th82JBABgsk/s1600-h/image%25255B23%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh3.googleusercontent.com/-2UvD4mLWrpI/VX_vf12Zp5I/AAAAAAAAAxU/OKoeqI8S3b8/image_thumb%25255B15%25255D.png?imgmax=800" width="400" height="118"></a></p> <p>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.</p> <h1><a name="section8">TypeScript’s Xrm API Documentation</a></h1> <p>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.</p> <p>Robust documentation has been provided to the TypeScript definition files, largely borrowed from <a href="https://msdn.microsoft.com/en-us/library/gg328255.aspx" target="_blank">Microsoft’s own documentation</a>. This provides a remarkable IntelliSense experience. However, with TypeDoc, I’ve created a navigable documentation page to help with understanding it:</p> <p><a title="https://6ix4our.github.io/Xrm-TypeScript-Documentation/index.html" href="https://6ix4our.github.io/Xrm-TypeScript-Documentation/index.html">https://6ix4our.github.io/Xrm-TypeScript-Documentation/index.html</a></p> <h1><a name="section9">Now You Haz Ready</a></h1> <p><a href="https://github.com/borisyankov/DefinitelyTyped/blob/master/xrm/xrm-tests.ts" target="_blank">There is a tests file in the repository</a> that should help demonstrate some of the basic concepts employed in the API definition. In all, I find that the definition file makes it <em>easier</em> 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.</p> <p>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!</p> <p>Cheers!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com1tag:blogger.com,1999:blog-5242498021352471451.post-63513081794513176462015-04-02T03:07:00.001-06:002015-04-02T17:13:23.490-06:00Debugging Dynamics CRM for Outlook<p>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 <em>myself</em> among them.</p> <p>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.</p> <p>“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 <em>will</em> return to the process of debugging JavaScript in Outlook.</p> <p>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:</p> <ol> <li>mousedown “The button is pressed down.” <li>mouseup “The button has been released.” <li>click “The button was pressed and released.”</li></ol> <p>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. </p> <p>It does; in every other browser, but not within the Outlook client. This is actually incredibly easy to test:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"><pre id="codeSnippet" class="csharpcode"><html><br> <head><br> <script type=<span class="str">"text/javascript"</span> src=<span class="str">"https://code.jquery.com/jquery-1.11.2.min.js"</span>></script><br> <script type=<span class="str">"text/javascript"</span>><br> $(document).ready(<span class="kwrd">function</span>(){<br> $(<span class="str">"#clickable"</span>).on(<span class="str">"mousedown"</span>, <span class="kwrd">function</span>() { alert(<span class="str">"Mouse is down."</span>);});<br> $(<span class="str">"#clickable"</span>).on(<span class="str">"mouseup"</span>, <span class="kwrd">function</span>() { alert(<span class="str">"Mouse is up."</span>);});<br> $(<span class="str">"#clickable"</span>).on(<span class="str">"click"</span>, <span class="kwrd">function</span>() { alert(<span class="str">"Mouse was clicked."</span>);});<br> });<br> </script><br> </head><br> <body><br> <span id=<span class="str">"clickable"</span>>Click on me to see the <span class="kwrd">event</span> pipeline.</span><br> </body><br></html></pre><br></div>
<p>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.</p>
<p>With that behind us…</p>
<p>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.</p>
<p>First, allow Visual Studio to do the dirty work by <em>deselecting</em> “Disable script debugging (Other)” from the Outlook machine’s Internet Options.</p>
<p><a href="http://lh4.ggpht.com/-WGe6zrVUAbU/VR0GuAjWkpI/AAAAAAAAAuM/kR8gU_q3MoA/s1600-h/image%25255B17%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-04ctdcQiuRU/VR0Gu5JbtdI/AAAAAAAAAuU/IwZjv3Ty4LQ/image_thumb%25255B15%25255D.png?imgmax=800" width="427" height="546"></a></p>
<p>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 <em>Microsoft.Crm.Application.Outlook.WebFormsHost.exe</em> matching the page you’re viewing. Each new window gets its own host process, so look carefully.</p>
<p><a href="http://lh3.ggpht.com/-_rcUlEi3zgQ/VR3NEB3dEZI/AAAAAAAAAvw/6yoMNPBgIzI/s1600-h/image_thumb%25255B50%25255D%25255B3%25255D.png"><img title="image_thumb[50]" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image_thumb[50]" src="http://lh6.ggpht.com/-J6sNVwlnzWU/VR3NEjMuZeI/AAAAAAAAAv4/mNoOEcsR-wg/image_thumb%25255B50%25255D_thumb%25255B1%25255D.png?imgmax=800" width="617" height="117"></a></p>
<p>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.</p>
<p>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:</p>
<ol>
<li>Launch Internet Options from the Control Panel. You <strong>cannot</strong> 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.
<li>Delete browsing history:<br><a href="http://lh4.ggpht.com/-aRFFNupwzMA/VR0Gxbq5srI/AAAAAAAAAus/bTouY3-ipTY/s1600-h/image%25255B58%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-IdJU1rxeBg8/VR0GylumGhI/AAAAAAAAAu0/Dm-5lplE5Ss/image_thumb%25255B52%25255D.png?imgmax=800" width="566" height="571"></a>
<li>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.
<li>Under “Advanced Troubleshooting”, click to “Delete Temporary Microsoft Dynamics CRM Client Files”.<br><a href="http://lh4.ggpht.com/-jFvopKe7HN8/VR0GzDROVCI/AAAAAAAAAu4/IwoImLD23es/s1600-h/image%25255B87%25255D.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-XEixRYgVVWU/VR0G0P264gI/AAAAAAAAAvE/ghljjVPUN48/image_thumb%25255B79%25255D.png?imgmax=800" width="581" height="518"></a></li></ol>
<p>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.</p>
<p>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!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-72894578534073672332014-08-26T21:53:00.001-06:002014-08-26T23:13:45.993-06:00A CRM Book and eXtremeCRM<p>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.</p> <p>However, while all these cards are coming together in the next few weeks, I’ll simply offer some filler. For those <a href="http://twitter.com/crmentropy" target="_blank">who follow me on twitter</a>, news of <a href="http://www.crm2013quickstart.com/" target="_blank">a new book with my name on it</a> is currently on the shelves. The CRM 2013 Quickstart guide is a new work, intended for the <strong>intermediate and advanced</strong> Dynamics CRM users. In particular, my contribution is the chapter “Developers, Developers, Developers” at the end.</p> <p>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 <a href="http://www.amazon.com/CRM-2013-QuickStart-David-Yack/dp/0981511872/" target="_blank">on Amazon</a> and through our publisher’s site: <a title="http://www.crm2013quickstart.com/Buy/Discount" href="http://www.crm2013quickstart.com/Buy/Discount">http://www.crm2013quickstart.com/Buy/Discount</a></p> <p>Finally, I’ll be attending <a href="http://www.extremecrm.com/" target="_blank">eXtremeCRM</a> 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. :)</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-31333339057290565112014-02-06T18:25:00.001-07:002014-02-09T11:37:00.144-07:00I’m not dead yet!<p>It’s about time that I come to you, the Dynamics CRM Community, <a href="https://community.dynamics.com/crm/default.aspx" target="_blank">you rich and vibrant thing</a>, with an apology and an explanation for my relative absence over these bitter winter months. Rest assured that I’m not dead. (And if that assures your <em>unrest</em>, then I can’t help you.)</p> <p>It has been ages, it seems, since I answered a forum post, and longer still since I published a blog post of technical merit. As such, I felt that I should at least fill what scarce readers I may still have (those devoted, loyal few) with some hope and information about what I’m working on for them.</p> <p>Firstly, and most looming, I will be at <a href="http://www.microsoft.com/dynamics/convergence/atlanta14/Default.aspx" target="_blank">Convergence 2014 in Atlanta</a>. Not simply as an attendee, mind you, but as a co-presenter with the indomitable <a href="http://georged.id.au/" target="_blank">George Doubinski</a>. Together, we’ll present “heroic” development topics under the <a href="http://www.crmug.com/" target="_blank">CRMUG</a> banner, and hope to see many of you there!</p> <p>Secondly, an unnamed book project should also be published this year, with my name found upon it. The details of this are intentionally vague at this point, as I’m still uncertain what more I can say about this work. However, I am honored to be involved, and hope I can deliver compelling and useful content for other Dynamics CRM developers.</p> <p>Lastly, I’ve been working tirelessly for my employer, <a href="http://www.avtex.com/" target="_blank">Avtex</a>, and have taken extra effort to identify and isolate many functional components that we can release as free community offerings. Obviously the intent is to stoke the fires of interest around Avtex in the Dynamics CRM space, but also to introduce the community to our “Avtex 360” concept: that to provide a better experience for our clients’ modern customers, we apply experienced and tech-savvy consultants and implementers across all points of interaction, and optimize those points with robust and tight integration between platforms and processes. Dynamics CRM is but one pillar of that mission, yet with strong <a href="http://www.avtex.com/avtex-news/2013/12/02/avtex-announces-strategic-partnership-with-sitecore" target="_blank">engagement</a> and <a href="http://www.avtex.com/avtex-news/2013/07/18/avtex-joins-the-2013-microsoft-dynamics-inner-circle" target="_blank">recognition</a> in <a href="http://www.avtex.com/avtex-news/2014/01/31/avtex-named-an-interactive-intelligence-platinum-elite-partner" target="_blank">several</a> industry venues (and a <a href="http://www.avtex.com/portfolio" target="_blank">varied and recognizable client portfolio</a>), Avtex is not only a clear leader, but possibly the best kept secret in the field of Customer Experience (CX).</p> <p>So, that’s where I’ve been and what I’ve been up to. However, as a <a href="http://mvp.microsoft.com/en-us/default.aspx" target="_blank">Microsoft MVP</a>, I’m continually looking for ways to squeeze in events and community face-time, so I’d like to also mention some up-coming events in which I’ll be participating in the coming weeks:</p> <ul> <li><a href="https://plus.google.com/u/0/events/c37nbpefici4e7vdok44oe7rm0g" target="_blank">Microsoft Dynamics CRM 2013 Panel Chat</a>, a Google+ Hangout hosted by the lovely and world-renowned <a href="https://plus.google.com/u/0/118424217619136752167/" target="_blank">Donna Edwards</a>. Feb. 20th @ 9:00AM PST (Noon EST) <li><a href="http://www.crmug.com/events/CRMUGCRMATE22714" target="_blank">CRMUG Webinar: Ask the Experts – Customization Best Practices for Dynamics CRM 2013</a>, a CRMUG member exclusive. Feb. 27th @ 11:00AM PST (2:00PM EST)</li></ul> <p>I’m also trying to back-fill some content that supplements a webinar I gave last year on <a href="http://www.crmug.com/events/crmpc110613" target="_blank">xRMVC</a>, which I did for CRM Partner Connections (CRMPC), an offshoot of CRMUG. That probably won’t see the light of day until April or May, but we’ll see. </p> <p>So, in closing, I’m not dead yet, and I hope to see you soon!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-12578141538572473952013-09-05T16:51:00.001-06:002013-09-05T17:19:40.970-06:00The CRM Field Guide… Guide<p>You might not know it, because I’ve been silent on the matter, but I am a contributing author to <a href="http://crmfieldguide.com/" target="_blank">The CRM Field Guide</a>.  Specifically, I authored Chapter 24: Rapid Development Best Practices.  The intent of the chapter is to introduce people with backgrounds similar to mine to the practices I have developed over the years to produce code for CRM 2011, well, rapidly.  However, before I delve into some of the meat and value of the book or my chapter, I’d like to journal my experience of writing for the book.</p> <p><a href="http://msdynamicsworld.com/story/story-crm-field-guide" target="_blank">It’s been stated before that the project was long-running</a>, with several starts and stops along the way.  To the credit of <a href="https://www.linkedin.com/in/donnaedwards" target="_blank">Donna Edwards</a>, <a href="http://www.linkedin.com/pub/julie-yack/0/5a/b2a" target="_blank">Julie Yack</a>, and <a href="http://www.linkedin.com/pub/joy-garscadden/3a/1b1/322" target="_blank">Joy Garscadden</a>, wrangling so many MVP authors was not a minor task.  As MVPs, we are all actively engaged in the Dynamics CRM community, while working day jobs.  These responsibilities conjointly leave precious little time for most other endeavors, family notwithstanding.</p> <p>I was brought into the project later, and given the opportunity to write about my passion: development.  Because my exposure to CRM 2011 was light at the time, from a technical standpoint, and because many other authors covered a great deal of the technical components (solutions, customization strategies, etc.), I decided to focus on the tools and processes I use to handle development projects from start to end—evolved from my experience with CRM 4.</p> <p>Deadlines were short, and yet I somehow ended up producing the single largest chapter, as measured in raw word counts.  It was amazing to write professionally, and the passion carried me quickly through my task.  To be a published author, for the first time, had been a dream as strong as my passion to become a professional software developer.  Marrying both experiences together is my crowning achievement.</p> <p>However, I remain dissatisfied with my content—deserved or not.  It has received high praises from reviewers and developers who are introducing themselves to Dynamics CRM, yet I feel as though it could be <em>better</em>.  Perhaps, sometime soon, I’ll produce something stronger and (in my eyes) worthy of my audience.  Apart from this private embarrassment, I have been biding my time in writing up anything because many other authors have continued to do it on my behalf.  (Thanks!)</p> <p>So why break the silence?  Because <a href="http://www.linkedin.com/in/jerryweinstock/" target="_blank">Jerry Weinstock</a>, of “Jerry Weinstock” fame, has produced <a href="http://www.crminnovation.com/blog/microsoft-dynamics-crm-training-guide/" target="_blank">a Training Curriculum addendum</a>, for the following roles:</p> <ul> <li>CRM Admin</li> <li>Power User</li> <li>Business Analyst</li> <li>IT Support</li> <li>Developer</li> <li>New User</li> </ul> <p>He has expertly fleshed out approximately 10 to 15 chapters from the book that serve as reference material for each role, and stands as a fantastic appendix to a fantastically dense and useful book!  This curriculum is affectionately referred to (by me) as The CRM Field Guide <em>Guide</em>, and will help each role focus on their specific area of expertise or interest.</p> <p>Jerry’s efforts will hopefully illustrate that the versatility of the book’s expansive content suites many purposes, and articulates its value in the library of any organization that works with Dynamics CRM.  Thank you, Jerry, for adding value to an immensely valuable resource.</p> <p>Where can you obtain it?  Well, because the curriculum is only useful in the context of the book, it’s available as downloadable content (DLC) for all who purchase The CRM Field Guide, either in hard or digital copies.  To celebrate this addition, <strong>I will provide a discount code for the digital copy of the book to the first 10 people who tweet a mention of the book (<a href="http://crmfieldguide.com/" target="_blank">crmfieldguide.com</a>), and include me (<a href="https://twitter.com/crmentropy" target="_blank">@crmentropy</a>) on it</strong>.  Look out for a Private Message from me!</p> <p>Cheers!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-71136033285455051562013-08-28T17:46:00.001-06:002013-08-28T17:46:24.622-06:00Entity.GetAttributeValue<T> Explained<p>The CRM 2011 SDK offers a handful of useful extensions over the previous versions that many Dynamics CRM developers have come to appreciate.  One in particular that I’ve only recently come to use is the <a href="http://msdn.microsoft.com/en-us/library/gg326129.aspx" target="_blank">Entity.GetAttributeValue<T></a> method.  I’ve seen it used in many places, and have started using it myself, but I never really fully understood how it can be expected to behave.  The Microsoft documentation—as with a great deal of the SDK—doesn’t offer much on this particular method, and no example code.</p> <p>I’ve found myself continuing to lean on <a href="http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.entity.contains.aspx" target="_blank">Entity.Contains</a> as a measure of safety, and checking the Entity indexer for type (using the “is” keyword), to make sure I wouldn’t violate a Type constraint.  My concerns have been alleviated today when I took a few minutes to run some scenarios through the method, to see what the results were.  There’s some good news I’d like to share.</p> <h2>The given key was not present</h2> <p>The only method parameter taken by Entity.GetAttributeValue<T> is the name of an attribute.  If that attribute is not present in the Entity instance, it will not generate an error.  Instead, the method will return a “default value” of Type T, or <em>null</em> if T is nullable.</p> <p>Be careful of assuming this means that the Entity contains your attribute, however, because it may not.  Entity.Contains will assure that a <em>null</em> return from Entity.GetAttributeValue<T> means that the attribute is truly <em>null</em>, and not just effectively <em>null</em> because it is missing.</p> <h2>Nullable Types</h2> <p>The non-primitive types provided by the SDK are all nullable (e.g. <strong>OptionSetValue</strong>, <strong>Money</strong>), meaning returns of these types will be a complete instance of the Type, or null.  However, the primitive types the SDK uses are not inherently nullable (e.g. <strong>int</strong>, <strong>bool</strong>).</p> <p>What happens if you pass a non-nullable type into the Type parameter T, and the value for requested attribute is, in fact, <em>null</em>?  Well, thankfully the SDK converts the <em>null</em> into a bitwise 0 value for T.  This is what I call the “default value”, and I’ll get to that in a moment.</p> <p>If you prefer to always receive <em>null</em>, instead of the “default value”, then you can pass a nullable-extended, primitive Type (e.g. int?, bool?, decimal?), and the SDK will cast the requested attribute accordingly.</p> <h2>Default values</h2> <p>A “default value” is the result of a <em>null</em> return being coerced into a non-nullable type.  The <em>null</em> return could be either: a) a missing attribute, or b.) a <em>null</em> value on the attribute.  When converting <em>null</em>, the SDK selects a bitwise 0 value for your type.  Consult the chart below for the expected returns:</p> <table cellspacing="0" cellpadding="2" width="477" border="0"><tbody> <tr> <td valign="top" width="297"> <p><strong>Type</strong></p> </td> <td valign="top" width="178"><strong>Return</strong></td> </tr> <tr> <td valign="top" width="297">Numerical (int, decimal, double)</td> <td valign="top" width="178">0</td> </tr> <tr> <td valign="top" width="297">Boolean</td> <td valign="top" width="178">false</td> </tr> <tr> <td valign="top" width="297">DateTime</td> <td valign="top" width="178">DateTime.MinValue</td> </tr> <tr> <td valign="top" width="297">Guid</td> <td valign="top" width="178">Guid.Empty</td> </tr> </tbody></table> <p>This can be handy, if you are performing calculations on primitive types, and would rather not write several lines of code to weed out <em>null</em> values (since performing any mathematical operation on <em>null</em> results in <em>null</em>).</p> <h2>Specified cast is not valid</h2> <p>If, by some misfortune, you pass a Type to the T parameter that is not Metadata-compatible with the actual value of the attribute you requested, this method will thankfully throw an InvalidCastException, rather than returning a default value.  This assures you that you’re not mismatching Types.</p> <p>For example, if an attribute is int and has an int value, but I pass ‘decimal’ to T, my code will throw an InvalidCastException.  Even though casting an int to a decimal is trivial for .Net, if my supplied Type does not match the Metadata schema, I will run into this exception.</p> <h2>Conclusion</h2> <p>So there you have it, a full rundown of how Entity.GetAttributeValue<T> works and how you can expect it to behave in your code.  Hopefully, you’ll realize like I did, that you can save yourself a lot of code by using this method and relying on its undocumented behaviors.  It was a fantastic add by the Dynamics CRM development team, and a hidden treasure for developers like me who became accustomed to writing all manner of attribute evaluations with previous versions of the product!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-83745373020720895172013-05-24T18:49:00.001-06:002013-05-29T17:45:48.328-06:00TypeScript, CRM 2011, and You<p>Those who know me closely know that I hold a certain disdain for JavaScript.  Not because I’m particularly bad at it (though some of my public and private code might put that to question), but because I believe I’m good at it.</p> <p>One thing that has always bothered me is how difficult it is to manage data structure contracts (read: types), throughout a large amount of code.  To achieve application-level fidelity, you need a specialized library, that calls for specialized object factories—breaking away from all native syntax, and making useful documentation generation and structure a miserable chore.  At least, that’s what it’s been for me.</p> <p>It didn’t have to be this way, but is.  Take, for example, <a href="http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/" target="_blank">the nearly useless “typeof” operator</a>.  At some point, somebody on the JavaScript language development team thought that types could be important, and then promptly died before his thought could infect other web developers.</p> <p>That’s what development comes down to for me:  data contracts.  Value or variable-based, I care not.  But, I want strong ones, flexible ones, abstracts, interfaces, inheritance, and predictability.  JavaScript developers either make their livings, or ruin their lives, by <a href="http://msdn.microsoft.com/en-us/magazine/ee336120.aspx" target="_blank">writing to edge-cases</a>—and in JavaScript API development, it’s all edges, all the way down.  If strong types were possible, I speculate that you could cut the jQuery library, for example, in half.  </p> <p>Whatever the shortcomings, they’re neither here nor there.  Because JavaScript only hit puberty in 2009, and it is still evolving.  Its ubiquity is undeniable, and its adoption and enrichment are accelerating.  Because of its slow maturity, it can pick and choose from more mature languages to implement advanced concepts.  This, of course, is driven from the myriad of developers that leave their comfort zones (perhaps reluctantly) to dive into this wishy-washy world of “nearly anything goes.”</p> <p>Let’s face it: IDEs give JavaScript developers most of their power. IntelliSense’s own JavaScript support has made leaps and bounds in recent iterations.  Still, most of the enrichment and “type” inference comes from documentation comments, in either the VSDoc or JSDoc formats.  Its native introspection capabilities, however, are like Reflector on meth-addicted steroids.  At runtime, you can achieve things that make .Net <em>bleed</em> with envy.</p> <p>The question, for me, has always been about bridging the gap: how do I posit stronger typing into my development, if not the language?  At first, I was drunk with prototypes and closures, and tried to produce <a href="https://github.com/6ix4our/Javascript-Inheritance" target="_blank">my own typing/inheritance model</a>.  Its quirks and desperate lack of syntactic approximation to stronger-typed languages left me to abandon it for something else.</p> <p><a id="fromExternal">In my search</a>, I’ve encountered <a href="http://smthngsmwhr.wordpress.com/2013/02/25/javascript-and-friends-coffeescript-dart-and-typescript/" target="_blank">a couple of strong contenders</a>.  <a href="http://www.dartlang.org/" target="_blank">Dart</a> is a promising project, and may go somewhere, but <a href="http://www.typescriptlang.org/" target="_blank">TypeScript</a> appears syntactically closer to <a href="http://addyosmani.com/blog/a-few-new-things-coming-to-javascript/" target="_blank">ECMA Script 6</a> (which will ultimately replace the current iteration of JavaScript).  The ECMA draft specification doesn’t appear to do much for type management, unfortunately—but that would be a major paradigm shift for JavaScript at this stage.  And honestly, I see TypeScript as the stepping stone to it.</p> <p>The big reason I hope this, is that all valid JavaScript is inherently valid TypeScript.  Meaning that I don’t need an interop library to implement rich and mature JavaScript libraries, nor to I have to cross-compile them into some alternate representation.  However, TypeScript benefits strongly from “definition” files, which help provide type associations to improve the TypeScript experience of those libraries.  I’m proud to announce today, that I have helped with two such definitions for use with Dynamics CRM 2011:</p> <ol> <li>Definition file for the Microsoft Xrm JavaScript namespace: <a title="https://xrm2011typescript.codeplex.com/" href="https://xrm2011typescript.codeplex.com/">https://xrm2011typescript.codeplex.com/</a> </li> <li>Definition file for the XrmServiceToolkit project: <br /><a title="https://xrmservicetoolkit.codeplex.com/" href="https://xrmservicetoolkit.codeplex.com/">https://xrmservicetoolkit.codeplex.com/</a>  <br />(you might have to get it from the Source: Scripts\typescript\XrmServiceToolkit.d.ts) </li> </ol> <p>I use these two together often, coupled with internal definition files for jQuery, JSON, and other common libraries.  The stock definition files have done a great job, so these are the only two new ones that I’ve needed, so far.  (Though, now that I’m getting into <a href="http://www.kendoui.com/" target="_blank">KendoUI</a>, I’d love to see definition files for it.)</p> <p>This is all well and good, but how is it supposed to help <em>you</em>?  There are many <a href="http://visualstudiomagazine.com/articles/2013/02/01/typescript.aspx" target="_blank">good</a> arguments <a href="http://msdn.microsoft.com/en-us/magazine/jj983351.aspx" target="_blank">surrounding</a> the <a href="http://msdn.microsoft.com/en-us/magazine/jj883955.aspx" target="_blank">adoption</a> of <a href="http://www.code-magazine.com/Article.aspx?quickid=1305051" target="_blank">TypeScript</a>, and <a href="http://www.xrmvirtual.com/events/crm2011_javascript_gayan_perera" target="_blank">other MVPs have addressed it in various venues</a>.  Personally, I take the following benefits, over raw JavaScript development:</p> <ul> <li>Types!  (If that wasn’t the first thing on this list, I should be soundly questioned.) </li> <li>Compiles to JavaScript by basically removing itself from the code, and applying some cohesive closure structures to the results.  (This is why all valid JavaScript is valid TypeScript.) </li> <li>C#’s interface and inheritance model!  (Multiple inheritance isn’t supported, but multiple interfaces are.  My C++ days are calling, and I let it go to voicemail.  I’m ok with this model.) </li> <li>Multiple method signatures!  (This doesn’t apply anything on the “compile” to JavaScript—yet—but makes the IDE experience nicer.) </li> <li>Generics!  (…coming in TypeScript 0.9) </li> </ul> <p>These are all concepts I encounter daily in my C# coding, and it’s nice to finally have a way to express them in my JavaScript development, without getting in my own way, or doubling the amount of work necessary to apply it.  However, as <a href="http://codebetter.com/johnpetersen" target="_blank">John Petersen</a> recently expressed in <a href="http://codemag.com" target="_blank">CODE Magazine</a>, <strong>“TypeScript compiles to pure JavaScript but that isn’t a license for ignorance about how JavaScript works.”</strong></p> <p>So, if you want to start learning TypeScript, the best way to start is to do the following:</p> <ol> <li>(Optionally) Read the <a href="http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf" target="_blank">TypeScript language specification</a> (but then, I’m into things like that) </li> <li>Install the <a href="http://www.microsoft.com/en-us/download/details.aspx?id=34790" target="_blank">TypeScript plugin for Visual Studio</a> (build support) </li> <li>Install the <a href="http://vswebessentials.com/" target="_blank">Web Essentials add-in for Visual Studio</a> (IntelliSense support—very basic, currently, but will identify errors at design-time) </li> <li>Follow the <a href="http://www.typescriptlang.org/Tutorial/" target="_blank">Quick Start guide for TypeScript</a> (to learn syntax basics) </li> </ol> <p>I find the following tweaks to Visual Studio’s options handy:</p> <ul> <li>Text Editor\TypeScript\Project: Uncheck all “Compile on Save” options; These collide with Web Essentials, and I prefer to use the “Build” action anyway. </li> <li>Web Essentials\TypeScript <ul> <li>“Compile to EcmaScript 3”:  <strong>False</strong> </li> <li>“Add generated files to project”:  <strong>True</strong> </li> <li>“Compile all TypeScript files on build”:  <strong>True</strong> </li> <li>“Compile TypeScript on save”:  <strong>False</strong> (But, if you want to, use this option, instead of the one from the TypeScript plugin—for now.) </li> <li>“Show preview window”:  <strong>False</strong> (This one just gets in my way, and is only really useful if you set the “compile on save” option.) </li> </ul> </li> </ul> <p>Then, you can use reference tags in your own TypeScript files, to include the definition files from above and start enjoying TypeScript in CRM 2011 development:</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <pre id="codeSnippet" class="csharpcode"><span class="rem">/// <reference path="definitions/Xrm2011.d.ts" /></span><br /><span class="rem">/// <reference path="definitions/XrmServiceToolkit.d.ts" /></span><br /></pre>
<br /></div>
<p>I hope you’ll be as interested in TypeScript as I am, because it’s a fantastic, open-source initiative from Microsoft—and it’ll prepare you for the next generation of JavaScript interpreters.</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-64450289445057203292013-04-11T22:11:00.001-06:002013-04-12T16:16:37.213-06:00Love Your UI: Icons for CRM<p>I’m going to make an unusual break from my normal kind of post to talk about customizing Dynamics CRM with paid utilities, and specifically about sourcing professional-appearing icons for CRM’s UI.  The topic doesn’t occur very often in the forums, and generally <a href="http://jlattimer.blogspot.com/2013/03/tips-on-finding-icons-for-custom.html" target="_blank">the advice has been to search Google</a>.</p> <p>I can’t discount that method, as I’ve used it in the past to locate royalty-free, attribution-free, and open-licensed sets of icons.  While the quality of many sets are great, the bulk of files are cumbersome to manage, and customizing them requires a significant investment of time and energy.  Looking into “modern” Microsoft interfaces with flattened icons, there are very few free options that match this style and look good doing it.  (However, if you’re looking for a good compilation of options, <a href="http://css-tricks.com/flat-icons-icon-fonts/" target="_blank">look no further than Chris Coyier</a>.)</p> <p>What an illuminating experience working with <a href="http://www.axialis.com/iconworkshop/" target="_blank">Axialis IconWorkshop</a> has been!  I inquired about the product about 6 months back, and was very graciously granted a gratis license to <a href="http://www.axialis.com/stock-icons/pure-flat-2013-toolbar.html" target="_blank">their full “Pure Flat” icon sets</a>.  I’ve had a handful of opportunities to use them, since, in conjunction with the IconWorkshop to author and customize the results.  Here’s a breakdown comparison of my previous “Google discovery” experience, and using a professional tool:</p> <h3>Locating an Icon</h3> <h5>Using Google:</h5> <p>Generally, I don’t use Google to find a single icon.  There is a significant amount of danger for violating copyright and intellectual-property rights.  Icon authors are hard working people too, and icon theft is one of the unspoken undercurrents of web applications, due in part to lazy people like I used to be.</p> <p>So, the last few times that I used Google, I went straight for “open-source, royalty-free, copyright-free” icon libraries.  There are many, but obtaining them from reputable sites can take some work.  Then, they are bundled into zip files (typically), and generally contain thousands or tens-of-thousands of icon files.  Filenames are the primary descriptors to search on, so if nothing turns up for a basic term, trying variations… or at worst, scanning through thumbnails, are best bets.</p> <p> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="360"><strong>Experience Ratings (1 best – 5 worst)</strong> </td> <td valign="top" width="58"> </td> </tr> <tr> <td valign="top" width="360">Time Consumption </td> <td valign="top" width="58"><strong>4</strong></td> </tr> <tr> <td valign="top" width="360">Skill Required</td> <td valign="top" width="58"><strong>2</strong></td> </tr> <tr> <td valign="top" width="360">Efficiency of Desired Outcome</td> <td valign="top" width="58"><strong>5</strong></td> </tr> </tbody></table> </p> <p>Finding icons that are legal to use can be a struggle, and sorting and managing the various packing and naming conventions often leave much to be desired when it comes to cataloging or describing collections.</p> <h5>Using IconWorkshop:</h5> <p>Searching through icons that are imported into Axialis Librarian is a fast process, and only made faster, I think, due to indexing of the files.  This indexing extends to metadata keywords, but unfortunately the Axialis icon sets don’t come preloaded with any (at least not by my sampling).  Adding your own keywords takes time, but can certainly help improve it.  For the basis of rating this experience, though, I will not consider it an advantage.</p> <p>When it comes to the image you want to use, Axialis has many libraries with an impressive number of icons, but they don’t yet have a “full set” purchase experience—unless you use their in-site contact form to inquire about it.  Their prices are fair for long-term use, and more importantly, they include “base” icon images and “overlay” images that can be easily combined to create new permutations easily.  Searches will generally turn up both, however variety is going to cost you.  That said, it’s generally easy to figure out which set likely contains the candidate icon you want.</p> <p>Thankfully, you can import assets from other libraries (especially any “free” sets you may already have), and the IconWorkshop can be useful for searching those, as well.  Depending on how you look at it, Axialis icon sets are not given first-class status over other libraries--and that’s either noble, or a lost opportunity. </p> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="360"><strong>Experience Ratings (1 best – 5 worst)</strong> </td> <td valign="top" width="58"> </td> </tr> <tr> <td valign="top" width="360">Time Consumption </td> <td valign="top" width="58"><strong>4</strong></td> </tr> <tr> <td valign="top" width="360">Skill Required</td> <td valign="top" width="58"><strong>2</strong></td> </tr> <tr> <td valign="top" width="360">Efficiency of Desired Outcome</td> <td valign="top" width="58"><strong>4</strong></td> </tr> </tbody></table> <p>While IconWorkshop helps with searching and organizing, Axialis’ icon sets are hamstringed by lack of useful keyword metadata accompanying their files.  They could have taken a “2” or “1” rating in the efficiency department, and probably lower in other areas.  However, the improved organization and the search capabilities maintain a slight edge over searching through the file system with something like <a href="http://www.mythicsoft.com/page.aspx?type=agentransack&page=home" target="_blank">Agent Ransack</a>.</p> <h3>Icon Set Quality</h3> <h5>Using Google:</h5> <p>“Free” icon sets come in varying styles and quality, so it’s hard to judge them collectively.  Often, it’s difficult to find a icon that comes in several native sizes.  Most “free” sets offer one or two sizes, and are often capped at 32x32, so scaling up or down impacts quality by producing pixelated or blurry results, respectively.  Within Dynamics CRM, 32x32 and 16x16 are used throughout the ribbons, grids, and menus; however, custom controls and pages can benefit from larger or smaller icons.  I have often found myself repeating the searching phase to find several icons that closely match each other in the various sizes.</p> <p>File formats are another issue, although generally minor given a good image editor.  Sets generally come in one or two formats, and they may or may not implement transparency.  It becomes important to check and convert, where necessary, to meet your needs.  (JPEG and GIF to PNG, for example.  Maybe that’s only <em>my</em> need, so your mileage may vary.)</p> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="360"><strong>Experience Ratings (1 best – 5 worst)</strong> </td> <td valign="top" width="58"> </td> </tr> <tr> <td valign="top" width="360">Time Consumption </td> <td valign="top" width="58"><strong>3</strong></td> </tr> <tr> <td valign="top" width="360">Skill Required</td> <td valign="top" width="58"><strong>3</strong></td> </tr> <tr> <td valign="top" width="360">Efficiency of Desired Outcome</td> <td valign="top" width="58"><strong>3</strong></td> </tr> </tbody></table> <p>Across the board, for most cases, if you find an icon you want, and are either lucky enough to have it looking good in every size you need it, or content with visual scaling effects, this is not a bad option.  In my experience, however, it tends to be fairly mediocre.</p> <h5>Using Axialis Icons:</h5> <p>The best thing I can say:  256x256 all the way down to 16x16 of hand-crafted icon goodness.  Each set comes in ICO, BMP, and PNG formats, which covers the Web and Windows spectrum nicely.  On top of this, overlays are separated into their own files with transparency masks as companions.  These only factor into the ratings of this category insofar as they also come in native resolutions that are clean, well-scaled, and visually appealing at all sizes; and also that Axialis has pre-combined many “obvious” overlay and base image permutations.</p> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="360"><strong>Experience Ratings (1 best – 5 worst)</strong> </td> <td valign="top" width="58"> </td> </tr> <tr> <td valign="top" width="360">Time Consumption </td> <td valign="top" width="58"><strong>1</strong></td> </tr> <tr> <td valign="top" width="360">Skill Required</td> <td valign="top" width="58"><strong>1</strong></td> </tr> <tr> <td valign="top" width="360">Efficiency of Desired Outcome</td> <td valign="top" width="58"><strong>2</strong></td> </tr> </tbody></table> <p>Having pre-built ranges and formats adds a tremendous amount of space to the icon libraries, but the convenience of always having a size and format that works without additional thought is hard to trade away after experiencing it.  The quality and appearance of each image is strikingly good.  However, I do wish the files had an SVG or font-based format—I haven’t needed those for CRM yet, so that doesn’t affect my rating.</p> <h3>Customizing an Icon</h3> <h5>Using GIMP:</h5> <p>I’m not going to throw Google under the bus in the image editing department.  There are lots of icon editors available, and image manipulation suites.  My personal favorite is <a href="http://www.gimp.org/" target="_blank">GIMP</a>.  It has many of the features I need for advanced image editing, and it’s open source.  After 10 years, I’m fairly comfortable performing a wide variety of tasks.</p> <p>Unfortunately, small images don’t feel comfortable in suites meant for larger ones, but it works.  Layers are especially handy for putting together transparency masks and overlays… but overlays are uncommon to find in free icon sets, so most overlays I’ve used were custom produced, adding a lot of time for clean results.</p> <p>GIMP’s main advantage is its tremendous image editing capabilities—professional caliber features.  However, its learning curve is equally tremendous, and I never quite found the time to automate some repeated tasks.  It does, however, produce superior quality.</p> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="360"><strong>Experience Ratings (1 best – 5 worst)</strong> </td> <td valign="top" width="58"> </td> </tr> <tr> <td valign="top" width="360">Time Consumption </td> <td valign="top" width="58"><strong>5</strong></td> </tr> <tr> <td valign="top" width="360">Skill Required</td> <td valign="top" width="58"><strong>4</strong></td> </tr> <tr> <td valign="top" width="360">Efficiency of Desired Outcome</td> <td valign="top" width="58"><strong>4</strong></td> </tr> </tbody></table> <p>Unfortunately, GIMP really just helps me “limp” with free icons, helping me cleanup scaling quirks, add custom overlays, or modify palettes.  The time investment is not insignificant, though.  I just didn’t realize it could be so much better.</p> <h5>Using IconWorkshop and Axialis Icons:</h5> <p>IconWorkshop has a feature that will compile and combine in all permutations, the overlays and base images you specify, to automatically produce an array of sizes and decorations without additional effort.  This is one of the faster ways to simply knock-out the 32x32 and 16x16 sizes I desire for CRM 2011.  </p> <p>The image editing capabilities of IconWorkshop are lackluster, and just advanced enough to satisfy the needs of basic manipulation.  Thankfully, I find myself working within their base+overlay formulas well enough that I haven’t had to step outside of IconWorkshop for anything more advanced.  It’s a borderline comfort, but it fits well for the purpose.</p> <p>It’s obvious that combining images is IconWorkshop’s strong suit, and that’s why Axialis’ icon sets are amazing within it.  The sets can stand alone, and IconWorkshop can do its deal with any source, but together they offer a purpose-built system that streamlines the whole process of tailoring icons—if you require it.  Again, Axialis has taken the liberty of combining common base and overlay permutations and included them in their large icon set files, so that reduces the need for customizing in the first place (or simplifies recombinant decoration).</p> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="360"><strong>Experience Ratings (1 best – 5 worst)</strong> </td> <td valign="top" width="58"> </td> </tr> <tr> <td valign="top" width="360">Time Consumption </td> <td valign="top" width="58"><strong>2</strong></td> </tr> <tr> <td valign="top" width="360">Skill Required</td> <td valign="top" width="58"><strong>3</strong></td> </tr> <tr> <td valign="top" width="360">Efficiency of Desired Outcome</td> <td valign="top" width="58"><strong>2</strong></td> </tr> </tbody></table> <p>By using a simpler tool and products that are built to work with it in an optimized fashion, I have shaved a lot of time from the process of building a slick-looking, custom UI within Dynamics CRM.</p> <h3>Average Scores:</h3> <table cellspacing="0" cellpadding="2" width="420" border="0"><tbody> <tr> <td valign="top" width="276"> <p><strong> </strong></p> </td> <td valign="top" width="66">“Free”</td> <td valign="top" width="59">Axialis</td> </tr> <tr> <td valign="top" width="276">Time Consumption </td> <td valign="top" width="66"><strong>4</strong></td> <td valign="top" width="59">2.33</td> </tr> <tr> <td valign="top" width="276">Skill Required</td> <td valign="top" width="66"><strong>3</strong></td> <td valign="top" width="59">2</td> </tr> <tr> <td valign="top" width="276">Efficiency of Desired Outcome</td> <td valign="top" width="66"><strong>4</strong></td> <td valign="top" width="59">2.66</td> </tr> </tbody></table> <p>I’m starting to understand the adage: “It’s not nobler to do by hand, what can be better and faster done with a tool, when lunch is on the line.”</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com2tag:blogger.com,1999:blog-5242498021352471451.post-82401257874253714082013-02-28T20:04:00.001-07:002013-02-28T22:13:42.258-07:00High Availability Workflows<p>Since joining <a href="http://www.avtex.com" target="_blank">Avtex</a>, I have been able to expand my horizons and gain exposure to customers with unique needs.  I try, as hard as possible, to incorporate or build on top of CRM’s out-of-box experience, and refrain from writing code I don’t have to.  To that end, I’d like to share a simple solution to making Workflows trigger while they’re deactivated for updating.</p> <p>It’s no secret that business processes change on-the-fly.  Implementing changes to active Workflows can be tricky, from an availability standpoint.  Most companies adopt a routine of modifying Workflow designs afterhours, or with operations momentarily held until the modification is complete.  This presents a dynamic and potentially troubling hurdle for “always on” companies.</p> <p>Because Workflows are listeners to CRM operations, rather than direct participants, any downtime with a particular Workflow means that it’s no longer listening to events.  This allows for the potential of unapplied business logic, and can be very difficult to diagnose or troubleshoot.</p> <p>Though the space of downtime can be reduced to mere minutes—by developing in an alternate environment and shipping the updated Workflow in as a Solution—the window of opportunity for actions to tip-toe past a disabled Workflow still exists.  For some companies, this is simply unacceptable.</p> <p>However, you can use the out-of-box Workflow abilities to create high availability Workflows that can be taken offline, modified, and then reactivated, all without missing a single event that was triggered while the Workflow was offline.  This works by splitting the Workflow’s functionality into two separate Worfklows:</p> <ol> <li>An event listening “Dispatcher” Workflow; and</li> <li>A “Business Logic” application Workflow</li> </ol> <p>By isolating the business logic into a “child Workflow” which is called by its corresponding Dispatcher, one can take the Business Logic offline, while leaving the Dispatcher functional.  This allows the configured triggers of the Dispatcher to operate continuously, though the step which calls the Business Logic counterpart will fail during the downtime.</p> <p>Though the Dispatcher jobs enter a “Waiting” state, they will be easy to identify (especially if you allow them to delete themselves when they’re successful) in order to resume.  This behavior is generally sufficient enough to allow a wider window for Business Logic adjustment, without requiring additional intervention to process the new logic against records that are awaiting to execute the new logic.  That brings up another excellent advantage to this pattern:</p> <blockquote> <p><strong>With Dispatchers, you can immediately terminate existing logic and immediately register all further processing against future logic.</strong></p> </blockquote> <p><em>Note:  You cannot retarget a different workflow, as that would require taking the Dispatcher offline—which defeats the purpose.  The System Job acts as a cloned instance of a Workflow, so the Dispatcher will always target a specific, business-logic Workflow.  You can approximate a retargeting scenario with Dispatcher juggling, but it would involve trigger overlapping mitigation.</em></p> <p>Here’s an example scenario that uses a Dispatcher to update an Account using the Dispatcher and Business Logic pattern:</p> <p>First, create the Business Logic workflow, and for “Available to Run” select “As a child process”.  Remove all selections from “Options for Automatic Processes”.</p> <p><a href="http://lh5.ggpht.com/-tZcBRRoLnYI/UTAas09t2GI/AAAAAAAAAgY/hLmwo3GF2XE/s1600-h/image%25255B38%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-r7s7feYLEzU/UTAataVcPwI/AAAAAAAAAgg/xRT5S1APqQQ/image_thumb%25255B26%25255D.png?imgmax=800" width="599" height="453" /></a></p> <p>Then, create the Dispatcher workflow with the “Options for Automatic Processes” setting you desire, and configure it to call your Business Logic workflow.</p> <p><a href="http://lh4.ggpht.com/-Yv85K7waOeY/UTAatl4lR9I/AAAAAAAAAgo/0IGY_PHHnFo/s1600-h/image%25255B37%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-ZM7kA_ieIH8/UTAauCi0mGI/AAAAAAAAAgw/kpPHJVk-CdA/image_thumb%25255B25%25255D.png?imgmax=800" width="599" height="423" /></a></p> <p>You may now activate both.  Your Dispatcher is diligently watching the events, and the Business Logic is processing your rules.</p> <p>Here is what happens when you deactivate the Business Logic workflow to make modifications:</p> <p><a href="http://lh4.ggpht.com/-2dBus3gFDTI/UTAau4LkUZI/AAAAAAAAAg4/KzuBM28vIHk/s1600-h/image%25255B36%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh5.ggpht.com/-N-Vqpa0Zi-s/UTAavFMsTSI/AAAAAAAAAhA/BtVS-TdAr_E/image_thumb%25255B24%25255D.png?imgmax=800" width="599" height="113" /></a></p> <p>My example uses a Dispatcher that listens to Account creation, so when I create a new account, here is what I see in the “Workflows” associated to it:</p> <p><a href="http://lh4.ggpht.com/-_zyXK-dU9Po/UTAavqZB29I/AAAAAAAAAhI/RT0Jn3RpC5w/s1600-h/image%25255B35%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-3oPQDJ6U7yQ/UTAavyjqW3I/AAAAAAAAAhQ/pNfxh0wGKpE/image_thumb%25255B23%25255D.png?imgmax=800" width="599" height="237" /></a></p> <p>As you can see, the Dispatcher caught the event, and then entered a “Waiting” state.  If we examine the job, we can see the error:</p> <p><a href="http://lh5.ggpht.com/-l7RzJQaJf3A/UTAawKPgcAI/AAAAAAAAAhY/nfQNkAG4fjg/s1600-h/image%25255B34%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh6.ggpht.com/-JCuP9mhrm-w/UTAawrVXIpI/AAAAAAAAAhg/ZUWSNVVe-Zo/image_thumb%25255B22%25255D.png?imgmax=800" width="599" height="403" /></a></p> <p>It failed on the step that calls my Business Logic.  This job will remain in this state until I resume it.  After completing my modifications to Business Logic, I’ll reactivate it.  Then, I need to identify all my outstanding Dispatcher jobs:</p> <p><a href="http://lh4.ggpht.com/-bqVyT5EBn9I/UTAaxBRHpTI/AAAAAAAAAho/5KW6ig0-r0M/s1600-h/image%25255B33%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-uUvXXYeZfQY/UTAaxbVOuVI/AAAAAAAAAhw/zNdUopfDNhQ/image_thumb%25255B21%25255D.png?imgmax=800" width="599" height="230" /></a></p> <p>Then, resume them with the confidence that I have missed no important triggers while my Business Logic was momentarily offline:</p> <p><a href="http://lh5.ggpht.com/-WtaFsodyQP0/UTAaxyABoFI/AAAAAAAAAh4/9xXIEwHegSU/s1600-h/image%25255B42%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-TRtNiG1kXJE/UTAayZPOJ3I/AAAAAAAAAiA/v2VPENctgfQ/image_thumb%25255B28%25255D.png?imgmax=800" width="599" height="220" /></a></p> <p>That said, I always perform a quick validation, just to be sure:</p> <p><a href="http://lh6.ggpht.com/-dFo2sA8Hd74/UTAaymfjGcI/AAAAAAAAAiI/ExfCZLY8kXY/s1600-h/image%25255B46%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://lh4.ggpht.com/-EvQlNXsQvyM/UTAazJ4_V_I/AAAAAAAAAiQ/K9fPC63sD0Q/image_thumb%25255B30%25255D.png?imgmax=800" width="599" height="158" /></a></p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com2tag:blogger.com,1999:blog-5242498021352471451.post-86065524021143406942013-02-11T16:53:00.001-07:002013-02-11T16:53:36.010-07:00A Potent Cocktail: ExecuteMultiple and LINQ<p>I love it when technologies using the same framework marry together like peaches and cream.  Today, I want to cover the intersection of CRM 2011’s new <a href="http://msdn.microsoft.com/en-us/library/jj863631.aspx" target="_blank">ExecuteMultiple capabilities</a> and my love of <a href="http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx" target="_blank">LINQ</a>.  Just to be clear, I’m <strong>not</strong> talking about using LINQ provider for CRM, though you can certainly use that to produce a collection of records upon which to perform some operation in bulk.</p> <p>Instead, I’d like to show you an elegant snippet of code that demonstrates the power of ExecuteMultiple with the cleanliness of succinct LINQ.  Given an EntityCollection —<em>someRecords— </em>suppose that you need to increment some integer —<em>my_integer—</em> on each of the contained records.  For the purposes of this example, I’ll be using the late-bound <a href="http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.entity.aspx" target="_blank">Entity</a> type.</p> <pre class="csharpcode"><span class="rem">// Start our request with some basic initialization</span>
ExecuteMultipleRequest bulkIncrementRequest = <span class="kwrd">new</span> ExecuteMultipleRequest()
{
Settings = <span class="kwrd">new</span> ExecuteMultipleSettings()
{
ContinueOnError = <span class="kwrd">true</span>,
ReturnResponses = <span class="kwrd">true</span>
},
Requests = <span class="kwrd">new</span> OrganizationRequestCollection()
}
<span class="rem">// Compile the collection of requests</span>
bulkIncrementRequest.Requests.AddRange( from record <span class="kwrd">in</span> someRecords.Entities
<span class="kwrd">where</span> record.Contains( <span class="str">"my_integer"</span> )
select <span class="kwrd">new</span> UpdateRequest()
{
Entity = <span class="kwrd">new</span> Entity( <span class="str">"someRecord"</span> )
{
Id = record.Id,
Attributes = {
<span class="kwrd">new</span> KeyValuePair( <span class="str">"my_integer"</span>,
( ( Int32 ) record[ <span class="str">"my_integer"</span> ] ) + 1 )
}
}
} );
<span class="rem">// Excute the requests</span>
ExecuteMultipleResponse bulkIncrementResponse = ( ExecuteMultipleResponse ) service.Execute( bulkIncrementRequest );
<span class="rem">// Check "IsFaulted" to determine if any of the submitted requests failed</span>
<span class="kwrd">if</span> ( bulkIncrementResponse.IsFaulted )
{
Int32 errorCount = ( from incrementResponse <span class="kwrd">in</span> bulkIncrementResponse.Responses
<span class="kwrd">where</span> incrementResponse.Fault != <span class="kwrd">null</span>
select incrementResponse ).Count();
}</pre>
<p>By using LINQ to inject the <a href="http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.organizationrequestcollection_members.aspx" target="_blank">AddRange</a> method of <a href="http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.messages.executemultiplerequest.requests.aspx" target="_blank">Requests</a>, I was able to compound the code that loops through each record, selects the original value, increments it, and produces a request to update the record.  </p>
<p>Keen observers notice that I created a new Entity object from the old one; this is a best-practice to avoid triggering updates on attributes undesirably.  However, it also allows me to perform the increment operation inline.  I’m sure you could inject this operation into a secondary where statement, but I think that makes the query logic less readable.  But your mileage may vary.  :)</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-22937703467178000552013-02-06T06:26:00.001-07:002013-04-12T16:22:17.407-06:00Add Parameters to CRM 2011 Lookup Dialog<h2>Alternate Title: How to hide the “New” or “Properties” button from the CRM 2011 Lookup Dialog.</h2> <p>Following on the heels of <a href="http://crmentropy.blogspot.com/2013/02/custom-crm-2011-form-notifications-for.html" target="_blank">yesterday’s post</a>, I have finally discovered a way to eliminate the pesky “New” and “Properties” buttons from the Lookup dialog.  This was, again, easier accomplished in the previous version of CRM, with the following code:</p> <div class="csharpcode"> <pre class="alt"><span class="lnum"> 1: </span>crmForm.all.<lookup>.AddParam(<span class="str">"ShowNewButton"</span>, 0);</pre>
</div>
<p>As we’ve seen before, this function did not disappear from CRM 2011—it was simply moved.  Now, this function is invoked somewhat implicitly via a behavioral association to a highly organized JavaScript object structure.  Yet again, hours of pouring over Developer Tools in Internet Explorer (this time with a lot more Profiling and debugging), I have figured out how Microsoft does it.</p>
<p>Here’s the new way to hide the “New” button:</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><span class="kwrd">var</span> lookupControl = Sys.Application.findComponent(<span class="str">"some_lookupid"</span>);</pre>
<pre><span class="lnum"> 2: </span> </pre>
<pre class="alt"><span class="lnum"> 3: </span><span class="kwrd">if</span> (lookupControl != <span class="kwrd">null</span>)</pre>
<pre><span class="lnum"> 4: </span>{</pre>
<pre class="alt"><span class="lnum"> 5: </span> lookupControl._element._behaviors[0].AddParam(<span class="str">"ShowNewButton"</span>, 0);</pre>
<pre><span class="lnum"> 6: </span>}</pre>
</div>
<p>Like most of the things on this blog, this is highly unsupported, but I personally believe that this is a harmless hack.  There is one caveat, however, to the above code:</p>
<ul>
<li>The ‘_behaviors’ member is a collection of references to classes.  For every Lookup I could find, there was only one entry, and it exposed the “AddParam” function.  Conceivably, there could be other Lookups with multiple behaviors, and the first item in ‘_behaviors’ may not be the one you want.  You have been warned.</li>
</ul> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com5tag:blogger.com,1999:blog-5242498021352471451.post-7503720651348611572013-02-05T06:15:00.001-07:002013-04-12T16:22:17.413-06:00Custom CRM 2011 Form Notifications for UR12<p><strong>[UPDATE:</strong> 2013.04.12 I added some additional tricks to this code, at the bottom.<strong>]</strong></p> <p>Before Update Rollup 12, it was relatively simple to use the original “form alert” hack (seen <a href="http://www.avanadeblog.com/xrm/2011/06/showing-custom-alerts-in-2011.html" target="_blank">here</a>, <a href="http://sliong.wordpress.com/2012/04/12/show-info-warning-error-message-in-crm-2011-notification-area-with-javascript/" target="_blank">here</a>, <a href="http://blogs.msdn.com/b/johnsullivan/archive/2011/11/02/crm-2011-custom-form-notification.aspx" target="_blank">here</a>, and <a href="http://mscrmbi.blogspot.com/2012/04/crm-2011-add-notifications-to-entity.html" target="_blank">here</a>) to produce custom, inline alerts and notices for the end user.  It’s a great feature of the form, and I wish I knew why using it is unsupported.</p> <p>Alas, many realized that these customizations would be undone by Update Rollup 12, and indeed they have.  So, allow me to show you what appears to be the “Microsoft” way of accessing the new form notification system.  The added bonus is that this method requires no additional libraries or external references, and should be cross-browser.  (Disclaimer: the following information was not released or documented by Microsoft; I discovered it after a few hours of pouring over Developer Tools in IE10.)</p> <p>The original hack could never have been cross-browser, because it relied on the “htc” behavior file which backed the original “crmNotifications” element.  Fortunately, these functions haven’t changed… just moved to a new home.  Here’s the old way (pre-UR12):</p> <div id="codeSnippetWrapper" class="csharpcode-wrapper"> <pre id="codeSnippet" class="csharpcode"><span class="kwrd">var</span> notificationsArea = document.getElementById(<span class="str">'crmNotifications'</span>);<br /><br />notificationsArea.AddNotification(<span class="str">'noteId1'</span>, 1, <span class="str">'namespace'</span>, <span class="str">'Message.'</span>);</pre>
<br /></div>
<p>And here’s the new way (post-UR12):</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">var</span> notificationsList = Sys.Application.findComponent(<span class="str">'crmNotifications'</span>);<br /><br />notificationsList.AddNotification(<span class="str">'noteId1'</span>, 1, <span class="str">'namespace'</span>, <span class="str">'Message.'</span>);</pre>
<br /></div>
<p>Both examples do the same thing in their respective CRM 2011 revisions.  This customization remains as unsupported as it ever was; however there is relatively little danger in using it.</p>
<p>Here are some additional tricks you can use:</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode">notificationList.SetNotifications();</pre>
<br /></div>
That will reset the notifications array with an empty set.  Also, you can hide the notifications area by using:
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode">notificationList.SetVisible(<span class="kwrd">false</span>);</pre>
<br /></div> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com12tag:blogger.com,1999:blog-5242498021352471451.post-8565236528199631332012-12-10T14:11:00.001-07:002012-12-10T14:11:00.946-07:00SSRS Execution Account Needs PrivUserGroup<p>I discovered, somewhat by accident, that if you specify an Execution Account in the SQL Server Reporting Services Configuration Wizard, the specified account will provide the security context for SSRS Web Services when using the CRM Reporting Extensions (SRS Data Connector).  Sound complicated?  It’s really not.</p> <p>The <a href="http://msdn.microsoft.com/en-us/library/ms181156.aspx" target="_blank">Execution Account</a> is SSRS’s way to connect to external resources which do not require login (or those for which no other credentials have been configured).  This keeps the SSRS service account safe from making any external connection with its own credentials.  CRM’s “SRS Data Connector” removes credential requirements in favor of an alternate impersonation scheme (which eliminates double-hop Kerberos, and makes reports easier to access).</p> <p>Perhaps that was obvious to people with more SSRS education, but I thought it was a maintenance account.  /shrug  A brand-new installation is likely the place you’ll run into this issue.  Unfortunately, the real causes of the failure are best viewed from the SSRS logs.</p> <p>The problem manifests as the following exception:</p> <blockquote> <p>"Cannot create a connection to data source 'CRM'."</p> </blockquote> <p>But ultimately is caused by this exception: </p> <blockquote> <p>"Immediate caller <SQL Server Reporting Services Execution Account> has insufficient privilege to run report as user <SID>"</p> </blockquote> <p>So the long and short of it:  if you specify an Execution Account for SSRS, and use CRM’s “SRS Data Connector”, then the Execution Account needs to be added manually to “PrivUserGroup”.</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com1tag:blogger.com,1999:blog-5242498021352471451.post-64822007149800547602012-10-18T10:28:00.001-06:002012-10-18T10:28:41.371-06:00Telerik wins a cookie!<p>I’ve had the fortunate opportunity to be working with Telerik (<a href="http://www.telerik.com">www.telerik.com</a>) tools in my Visual Studio development environment for a while now, and I like them.  <a href="http://www.telerik.com/products/memory-performance-profiler.aspx" target="_blank">JustTrace</a>, <a href="http://www.telerik.com/products/justcode.aspx" target="_blank">JustCode</a>, and <a href="http://www.telerik.com/products/decompiler.aspx" target="_blank">JustDecompile</a> are fantastic development accelerators that should be an integral part of any serious developer’s toolset.  However, it was an experience with a recent software update that really set Telerik apart, in my mind, from any other software I’ve used to date.</p> <p>Recently, Telerik has introduced a Control Panel utility that centrally manages the installation and download of their products.  It’s quite handy, and saves a great deal of time and effort.  While I was using it to process updates yesterday, the installation of Telerik’s <a href="http://www.telerik.com/products/orm.aspx" target="_blank">OpenAccess ORM</a> product failed.  I tried to update it once or twice more, through the Control Panel, and each time it failed, I used the “Send Feedback” button—thinking that perhaps the error was due to some flaw in the update, and maybe this report would be aggregated with others to help isolate a bug.</p> <p>I couldn’t have been more wrong.</p> <p>Unlike other software vendors, Telerik takes its feedback very seriously, and those simple little buttons that relay crash data back to vendors generally does nothing helpful for the user—unless you’re using a Telerik product.</p> <p>Today, I received an email from Petar Raykov, in the Telerik support team, who not only personally identified my reports, but suggested—very kindly—that I should consider shutting down Visual Studio when I apply updates, because file locks were likely the cause.</p> <p>Man, do I feel stupid and important all in the same breath.  Of course, I should have known to close VS2012; but didn’t think it would be a problem since I originally installed the components on my still-present VS2010 installation.  However, the fact that I was personally contacted by Telerik, after using just a simple button on the product to send off exception data, astounded me.  Compound that with the fact that I expressed no severity or need to address this problem, and what you get is the picture of a company that just <em>cares</em> about how its software works for <em>you</em>.</p> <p>Thank you, Petar.  Thank you, Telerik.  You’ve earned the highest marks in my book for quality of service and support by being proactive and concerned about the basic experience of your product.  I will continue to recommend your line of developer toolkits wherever I go, and share this story as I do it!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-46521702033597813192012-07-01T16:29:00.001-06:002012-07-01T16:29:03.525-06:00My Third MVP Award<p>Microsoft graciously renewed my MVP status for 2012, as I found out today. I don’t know why it keeps happening, but I love it and hope always to be worthy of it. Having grown much closer to my MVP compatriots this year, more than previous years thanks to the MVP Summit, I am honored again to be placed among their ranks.</p> <p>Ordinarily, I would have lots to say about it… but I can only thank Microsoft for yet another opportunity to continue in this capacity, and hope strongly that I will not disappoint the Dynamics CRM team in continuing to help steer the product’s development. Also, I thank the community that has supported me all these years, and hope to be worthy in their eyes as well.</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com2tag:blogger.com,1999:blog-5242498021352471451.post-54934572350808058392012-05-25T06:42:00.001-06:002012-05-25T06:42:09.566-06:00NDepend v4 Released<p>I’ve mentioned <a href="http://www.ndepend.com/" target="_blank">NDepend</a> a scant few times, mostly because I’ve used it in limited fashion.  Though <a href="http://www.ndepend.com/CQL.htm" target="_blank">CQL</a> was easy enough to learn, I found it difficult to quickly put together complex analytical queries against my code.  Patrick Smacchia answered my unannounced plight in the <a href="http://www.ndepend.com/NDependV4.aspx#" target="_blank">Version 4 release of NDepend</a> with the revolution that is <a href="http://www.ndepend.com/Features.aspx#CQL" target="_blank">CQLinq</a>.</p> <p>By bridging the best of the CQL and Linq worlds together, Patrick has truly delivered the most effective and rapid-use code quality tool for .Net development.  NDepend has moved from being a utility of convenience to a core necessity in my personal development.  Regardless of whether or not you have experience with code quality tools for .Net development, <a href="http://www.ndepend.com/NDependDownload.aspx" target="_blank">I highly recommend investigating NDepend</a>.</p> <p>I look forward to continuing my use and integration of this latest version into my projects and using the power of CQLinq to its fullest extent.  Thank you, Patrick!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-30926755194278259622012-04-29T13:41:00.001-06:002012-04-29T13:41:13.164-06:00CRM, Cookies, and You<p>I went out on an adventure to find out if I could pass extra data into a web service Message from the client, and discovered that it is possible to set a cookie at the browser (or an ISV page, if you’re into that kind of thing), and pick it up inside of a Plugin. There are a few limitations and gotchas to this process, not the least of which being that this is considered an unsupported customization.</p> <p>However, there are often interesting needs and situations for which you may want to pass extra data along to a Plugin, but don’t really have a good way to do it. For instance, I wanted to watch a sub-grid for changes to records and identify only those changes which were made while the parent record was opened. In this case, I wanted to catch an array of changes once the parent record was saved, and I needed this array to be specific to the singular “session” of the form’s lifetime on the screen. (If anyone can think of an alternate, supported method for this that doesn’t involve a ridiculous amount of return trips to CRM, I’d love to hear it.)</p> <p>Practically speaking, I was producing a rich audit trail with contextual links to changes with related records. Because this was for CRM 4, there was no existing audit feature as with CRM 2011—however, I’m fairly certain this process can be applied to CRM 2011 with the consideration that it may fail in sandbox mode.</p> <p>What I did was push indicators from the child window into a JavaScript array running on the parent window. Then, I serialized these indicators into a JSON string, and established a cookie (again, in JavaScript). By examining the “Request.Cookies” object at the plugin (after importing the necessary namespaces), I could identify and deserialize the contents and perform work at the Plugin.</p> <p>Also, I discovered that “Response.Cookies” can be loaded with information by an ISV page (though depreciated in CRM 2011, are still available for on-premise use) and also discovered by the Plugin. This can effectively overload a CRM web service transaction with extra information without messy things like temporary records (which will shoot SQL indexes to hell) and extra attributes.</p> <p>I ran into trouble, however, when trying to set a cookie from JavaScript within an ISV page. The Plugin would not identify this cookie, and I believe it’s due to the difference in the way the browser treats cookies from the runtime versus cookies from the domain (served in the HTTP response of the ISV page).</p> <p>So, what are the limitations and gotchas?</p> <ol> <li>THIS IS AN UNSUPPORTED CUSTOMIZATION</li> <li>CRM 2011 Plugins operating within sandbox mode will probably be prevented from accessing the “Request” or “Response” from the “Page” context. Again, I haven’t tried this with CRM 2011 yet, but that’s the assumption I’d have to make.</li> <li>The Plugin will only have access to the cookie from the “Page” context while operating synchronously.</li> <li>Cookies are persistent. Most web developers understand this, but it’s easy to forget. Once a cookie is set, it must be forcibly removed or allowed to expire. Never assume that a cookie will not have survived its previous instantiation.</li></ol> <p>Cookies can be a two-way street of information, so there are likely many different and exciting uses for them to extend CRM’s functionality and encourage cross-talk between various UI elements that may otherwise have no sensible means of sharing data. If you have used Cookies with CRM before, I’d love to hear what purpose they served!</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-42881462374015075912012-03-04T16:43:00.001-07:002012-03-04T17:30:03.719-07:00So This Is What I Missed…<p>I’ve successfully returned alive from my attendance of the <a href="http://www.2012mvpsummit.com/" target="_blank">Microsoft 2012 MVP Summit</a>.  This was a minor concern, given that I was stricken with a bout of vertigo that still troubles me to a lesser extent today.</p> <p><a href="http://crmentropy.blogspot.com/2011/02/its-been-quiet.html" target="_blank">I missed last year’s Summit</a>, and was quite anxious to attend this year’s event. This extended delay in participation allowed me to accrue more familiarity with the MVP world, and the topics reserved for NDA-backed channels. Thankfully, <a href="http://www.journeyteam.com/" target="_blank">JourneyTEAM</a> helped me attend during one of the largest projects I’ve ever been assigned. </p> <p>The single greatest thing I’m looking forward to in the Dynamics CRM 2011 updates to come will be [CENSORED].  Sorry, folks.  You won’t find me spilling the beans of Geek Vegas here, because after partaking in the greatest conference of MVP minds throughout the entire world, I have found an appreciated value in my nondisclosure agreement.</p> <p>Many folks don’t truly understand the impact or the purpose of this Summit.  Even as a second-year MVP, I didn’t fully understand.  In fact, based solely on the stories that do make it out of this event, an outsider may believe the experience to be purely about back-patting, drinking, and self-sustaining ego building.  I cannot state more emphatically than in bold text the following rebuttal:  <strong>this is not the case</strong>.</p> <p>That said, I was not surprised to learn that of 55 Dynamics CRM MVPs, our attendance total was 41.  That means that 3 out of every 4 Dynamics CRM MVPs were at the summit, providing a voice for the community directly to the product teams.  We truly represented every aspect of our community, from independent developers to ISVs, from small businesses to enterprises, and from end-users to administrators.</p> <p>Microsoft’s product teams generally have little or selective involvement in direct customer engagement.  Most of Microsoft’s public-facing customer involvement comes from either partners or Microsoft Support.  This layer of abstraction and occlusion, though necessary, provides little for a product team by the way of direction.  The MVPs are representative of the entire community, and help direct Microsoft’s products through updates, versions, and feature additions.</p> <p>We love it.  It was no more apparent than during some of the more heated discussions and debates that littered the entire Summit experience.  Yet, at the end of the day, we all gathered at various Seattle bars to unwind with rounds of beers and drinks with umbrellas (you know who you were).</p> <p>This isn’t a collection or even a community of experts.  It’s a family.  And I am damn proud to take part in it.</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com1tag:blogger.com,1999:blog-5242498021352471451.post-80752302029283130492012-01-07T13:21:00.001-07:002012-01-07T13:21:11.288-07:00XRM Virtual Presentation<p>On Jan. 10th, I’ll be making a presentation along such revered Dynamics CRM MVPs as <a href="https://twitter.com/#!/coloradojules">Julie Yack</a>, <a href="https://twitter.com/#!/scottsewell">Scott Sewell</a>, <a href="https://twitter.com/#!/edwardsdna">Donna Edwards</a>, <a href="https://twitter.com/#!/leontribe">Leon Tribe</a>, <a href="https://twitter.com/#!/Shan_McArthur">Shan McArthur</a>, and <a href="https://twitter.com/#!/mitchmilam">Mitch Milam</a>. Our topic matter will be specifically those lessons we’ve learned the hard way over our varied experiences with CRM.</p> <p><a href="http://www.xrmvirtual.com/">XRM Virtual</a> is an open-membership user group with a lean toward developers and integrators. If you’d like to register to attend this presentation, visit the <a href="http://www.xrmvirtual.com/events/mvp_lessons_CRM2011">Event Page</a>.</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-86344975208273707562012-01-01T16:19:00.001-07:002012-01-01T16:19:02.751-07:00Google+ Page for Dynamics CRM<p>Lately, I’ve been trying to coalesce information streamed around various channels to which I’m attuned into a new <a href="https://plus.google.com/b/117560607999887530349/">Google+ page for Dynamics CRM</a>.</p> <p>Personally, I’ve become a heavier <a href="https://plus.google.com/">G+</a> user than Facebook, and not just because of its rock-solid performance—but because of many important privacy and intellectual property practices.  I’d recommend it for anyone looking to break out of Facebook once and for all.</p> <p>LinkedIn is still a great professional resource for sourcing CRM talent and even assistance, so you’re sure to find great resources there too.  But its format and membership are rather rigidly defined compared to Facebook or Google+.</p> <p>In any event, I welcome any contributions and “circling” of the G+ page, and hope to make it an active and engaging space for the CRM community, apart from the <a href="http://social.microsoft.com/Forums/en-US/category/dynamics">Microsoft public CRM forums</a> where I can also be found.</p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0tag:blogger.com,1999:blog-5242498021352471451.post-68467222349381361252011-12-19T15:05:00.001-07:002011-12-19T17:01:23.130-07:00Using XML-based Plug-in Configuration<p>For more complicated and feature-rich Plug-in customizations for CRM, it can be appealing to use highly dynamic configurations. The Plug-in model offers simple string parameters to allow for the open interpretation by Plug-in developers. One of the more efficient and flexible configuration mechanisms is XML.</p> <p>With XML configuration, there are three methods that can be used to varying degrees of efficacy:</p> <ol> <li>Hard-parsing; dissecting XML with String manipulation (useful in dire situations) <li>XmlDocument parsing and node traversal; similar to JavaScript DOM manipulation and perhaps easier for web developers to grasp <li>XML-serialized classes; deserializing XML into one or more strongly-typed classes that represent the configuration</li></ol> <p>For the purposes of this post, I’m going to focus on the method that I prefer and find superior to the others: XML-serialized classes. The reason I believe this is superior is for the following reasons:</p> <ul> <li>Serialized classes can be versioned with namespace declarations; meaning that updating code and providing for new configuration specifications can preserve older versions <li>Hard-parsing and XmlDocument traversal requires significantly more code to determine what was passed <li>Serialization and deserialization work both ways; Plug-in configuration can be performed by a utility (think Silverlight!) that understands the .Net class representing the configuration, and easily construct the XML; this ability is simplified to a great extent with WCF Data Contracts (which we’ll get to in a moment) <li>Hard-parsing and XmlDocument traversal code requires more effort to update or alter the configuration schema <li>Hard-parsing and XmlDocument traversal work better in situations when the XML document and its contents are either <ol> <li>Very simple and statically defined <li>Totally unknown and dynamic</li></ol> <li>Serialized classes define a rigid standard and schema for the configuration, but also offer a significant amount of flexibility while simplifying the interpretation of the configuration</li></ul> <p>As a caveat, I should state that I’m extremely comfortable with XmlDocument use. I’ve used it many times, and found it a natural fit for my long experience with JavaScript DOM programming. However, I recently implemented a project that needed a highly structured and very robust configuration model, and decided to look for ways to reduce the amount of code I needed to write. Additionally, I needed the process to be flexible, as I might change my mind about the operational needs from the configuration as the code evolved.</p> <p>Starting with the concept of deserializing .Net classes from XML, I searched for the best method of implementation for CRM that I could identify. I found that there are a few ways within the .Net framework to serialize and deserialize classes into and from XML. Some are more flexible than others, but the CRM platform offers unique challenges that pretty much made my answer for me: WCF Data Contracts.</p> <p><a href="http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/">Why WCF Data Contracts?</a> Well, I like to deploy my assemblies to the database. This is a practice that helps assure the interoperability of my code with CRM Online.</p> <p>The problem with traditional, old-school XmlSerializer methods is that .Net requires the original assembly to be file-system accessible in order to reference for compilation into a “[foo].XmlSerializers.dll” assembly. If you really didn’t know what these assemblies were (as I didn’t) before now, allow me to explain. The XmlSerializer routines require strongly-typed interpretive classes that are Reflected out of the original assembly and built “on-the-fly” by the .Net CLR. It cannot achieve this with assemblies that exist only in memory, as database-deployed assemblies are. Therefore when CRM attempts to deserialize by calling these interpretive classes, they don’t exist—causing an “Object Is Not An Instance” exception.</p> <p>Experienced developers know that these XmlSerializer assemblies don’t have to be built “on-the-fly”, and they can certainly be assembled and distributed in conjunction with the original assembly. However, CRM doesn’t support a shared-assembly model for database deployment. The assemblies could be deployed to disk or GAC, but again this isn’t compatible with CRM Online.</p> <p>If you’re thinking, as I did, that perhaps the assemblies can be merged together with ILmerge and deployed together, think again. ILmerge generates a new AssemblyId attribute for the combined assembly metadata—which is only a problem for a the “[foo].XmlSerializers.dll” assembly because it strictly validates the AssemblyId of the calling code; and it imprints on the original assembly.</p> <p>Before I discovered WCF Data Contracts, I was desperate enough to output the generated code for the XmlSerializer assembly and inject it into my project. This is as ugly and highly ill-advised as it is time-consuming. So, if you’re considering XML configuration for CRM Plug-ins, I strongly recommend using WCF Data Contracts.</p> <p>For more reading, see <a href="http://msdn.microsoft.com/en-us/library/ms733127.aspx">the MSDN Article on WCF Data Contracts</a>.</p> <p>Some tricky “gotchas” with using WCF Data Contracts for newbies:</p> <ul> <li>The order of XML nodes must be alphabetically ordered by their declared Data Contract name; this is a deserialization optimization requirement, and can be massaged to a certain extent <a href="http://msdn.microsoft.com/en-us/library/ms729813.aspx">by using advanced Data Contract directives</a>. <li>There are no deserialized “attributes” for XML nodes. The only supported XML-node attributes are namespace declarations. Every Data Member is its own node, and its contents become the deserialized value.</li></ul> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com4tag:blogger.com,1999:blog-5242498021352471451.post-30102202683840143042011-10-18T01:53:00.001-06:002011-10-18T01:53:38.660-06:00Upgrade CRM 4 to 2011: For ITdiots<h3>Q: Who’s an ITdiot? A: Me.</h3> <p>I’ve been involved in the IT world since my early teen years. It started as the family computer expert, and evolved into advanced circuit configuration for ISPs and eventually a fulltime network administrator gig. All the while, I nurtured and evolved my passion for development.</p> <p>Ordinarily, this blog is dedicated to the later talent and my trials and tribulations therewith. However, I cannot deny that the foundations of my career and experience have solid roots in the IT realm. Having never acquired any formal education for either talent is what makes me, your friendly (mostly) neighborhood CRM MVP, an ITdiot.</p> <p>If it weren’t for Google, I wouldn’t have much of a career. While some things in the IT world have become intrinsically intuitive, I would be remiss to ignore the fact that my first real job at an Internet Helpdesk left me puzzled for longer than I care to admit as to why “.net” or “.org” worked to execute things on the computer, and “.com” was so much more prevalent than “.exe”.</p> <p>At any rate, I recently gave <a href="http://www.crmug.com/events/CRMUGITSupport10142011" target="_blank">a presentation for CRMUG geared toward the IT Crowd</a>—not the British comedy (although if you’re in IT and haven’t yet seen it, you <a href="http://www.imdb.com/title/tt0487831/" target="_blank">should</a>), but my <em>people</em>. So, the following guide complements that presentation and the material I covered, and all that I had wished to cover but ran out of time for. This is a basic list of the considerations I make when considering the move from CRM 4 to CRM 2011.</p> <h3>CRM 2011 On-Premise Upgrade Requirements</h3> <ul> <li>Windows Server 2008 SP2 or R2; 64-bit</li> <li>SQL Server 2008 SP1; 64-bit</li> <ul> <li>Recommend a different SQL server than what hosts CRM 4 (otherwise, it will upgrade the CRM 4 configuration and default org databases in-place)</li></ul> <li>Removal of any unsupported customizations (see IRAD at bottom)</li> <li>An active CRM Administrator account <a href="http://www.crmsoftwareblog.com/2011/07/user-mapping-error-upgrading-to-microsoft-dynamics-crm-2011/">http://www.crmsoftwareblog.com/2011/07/user-mapping-error-upgrading-to-microsoft-dynamics-crm-2011/</a></li></ul> <h3>What about Online?</h3> <h5>Pros:</h5> <ul> <li>Reduced IT overhead; from infrastructure to support</li> <li>Reduced deployment timeframe</li> <li>Automatic/Scheduled updating</li> <ul> <li>“Scheduled” becomes “Automatic” within a year</li></ul> <li>Aligns with Office 365 and SharePoint Online</li> <li>Provides an easy to use Internet Lead Capture feature</li> <li>Can be redeployed as 2011 On-Premise <li>Federated authentication is just around the corner (R7; Q4 2011 Service Update)</li></ul> <h5>Cons:</h5> <ul> <li>May not be ideal for integrated systems (ERP, Accounting, etc)</li> <ul> <li>Limited functionality connecting from CRM to external resource</li></ul> <li>No support for custom Workflow actions</li> <li>Limits on number of Workflows and custom entities (200?) <li>Externally hosted email router (on-premise, hosting provider)</li> <li>FetchXML reports only</li></ul> <h3>Helpful Overviews</h3> <ul> <li>The Official Word <a href="http://technet.microsoft.com/en-us/library/gg554717.aspx">http://technet.microsoft.com/en-us/library/gg554717.aspx</a> <li>Business and Technical Impact Considerations <a href="http://blog.sonomapartners.com/2011/04/upgrading-to-crm-2011-our-story.html">http://blog.sonomapartners.com/2011/04/upgrading-to-crm-2011-our-story.html</a> <li>Step-by-step guide <a href="http://weblogs.asp.net/pabloperalta/archive/2010/11/01/step-by-step-installing-crm-2011-on-premise-and-migrating-from-dynamics-crm-4-0-32-bits-on-premise.aspx">http://weblogs.asp.net/pabloperalta/archive/2010/11/01/step-by-step-installing-crm-2011-on-premise-and-migrating-from-dynamics-crm-4-0-32-bits-on-premise.aspx</a></li></ul> <h3>Upgrade Methods</h3> <ul> <li>Direct upgrade</li> <ul> <li>Universally considered the riskiest route</li> <li>Fastest/easiest option for GAC-deployed custom assemblies</li> <li>Use virtual machines for Intermediary transition to land CRM 4, and good testing space for CRM 2011: <a href="http://rondegiusti.wordpress.com/2011/03/01/steps-when-upgrading-migrating-from-ms-crm-4-to-crm-2011/">http://rondegiusti.wordpress.com/2011/03/01/steps-when-upgrading-migrating-from-ms-crm-4-to-crm-2011/</a></li></ul> <li>Import CRM 4 Org to virgin CRM 2011 install ("Microsoft Migration")</li> <ul> <li>Universally considered the safest route</li></ul> <ul> <li>Allows you to reserve a backup database copy and perform the import several times if necessary to massage the process for heavily customized CRM 4 environments</li></ul> <ul> <li>Doesn't import GAC and Disk deployed custom assemblies</li></ul> <ul> <li>Least impact to production environment and faster than using VMs <li>Requires some work to avoid the limitation of importing an org once <a href="http://www.dynamicscrmtrickbag.com/2011/04/08/migrating-from-crm-4-0-to-dynamics-crm-2011/">http://www.dynamicscrmtrickbag.com/2011/04/08/migrating-from-crm-4-0-to-dynamics-crm-2011/</a></li></ul> <li>Integration utility to ship CRM 4 data (Scribe, InaPort) <a href="http://blogs.msdn.com/b/crm/archive/2011/09/30/using-inaplex-inaport-for-data-integration-with-microsoft-dynamics-crm.aspx">http://blogs.msdn.com/b/crm/archive/2011/09/30/using-inaplex-inaport-for-data-integration-with-microsoft-dynamics-crm.aspx</a></li> <ul> <li>Handy for selective data import, obsoleting customizations that were problematic or could use changing</li> <li>Difficult to ship CRM 4 custom assemblies (use the CRM 4 Plugin Export utility to help)</li> <li>In short: a great way to break the "direct update" chain</li></ul></ul> <h3>Social Experiences</h3> <ul> <li>New Outlook Client behaviors: <a href="http://niiranen.eu/crm/2011/03/upgrade-gotchas-outlook-client-for-dynamics-crm-2011/">http://niiranen.eu/crm/2011/03/upgrade-gotchas-outlook-client-for-dynamics-crm-2011/</a></li> <ul> <li>Opt for 32-bit over 64-bit Outlook Client, at least for a while</li> <ul> <li>Silverlight compatibility issue; until Silverlight 5 rolls out. Many Marketplace solutions and customizations using Silverlight may not work in 64-bit Outlook.</li></ul> <li>No more favorite folders</li> <ul> <li>To restore, one must disable the Outlook 2010 Solutions module; this may also impact Marketplace solutions or desired functionality</li></ul> <li>Windows Live Essentials</li> <ul> <li>Avoid using, or be prepared repair installations of its component</li></ul></ul> <li>Old Outlook Client behaviors: <a href="http://blogs.msdn.com/b/ukcrm/archive/2011/04/22/crm-4-0-client-upgrade-to-crm-2011.aspx">http://blogs.msdn.com/b/ukcrm/archive/2011/04/22/crm-4-0-client-upgrade-to-crm-2011.aspx</a></li> <ul> <li>UR7 is compatible with CRM 2011 <li>Offline functionality is disabled</li></ul> <li>Moving from CRM 4 Online to CRM 2011 On-Premise: <a href="http://www.magnetism.co.nz/blog/11-04-15/Issues_Upgrading_from_Dynamics_CRM_4_0_to_2011.aspx">http://www.magnetism.co.nz/blog/11-04-15/Issues_Upgrading_from_Dynamics_CRM_4_0_to_2011.aspx</a></li> <ul> <li>Be sure to check that On-Premise users exist for mapping <li>Administrator account mapping should be manually mapped for accuracy</li></ul> <li>CRM 2011 may throw JavaScript errors, even when CRM 4 wasn't customized with JavaScript: <a href="http://blogs.msdn.com/b/emeadcrmsupport/archive/2011/08/31/crm-2011-form-errors-when-opening-non-customised-forms-object-doesn-t-support-property-or-method-form-load.aspx">http://blogs.msdn.com/b/emeadcrmsupport/archive/2011/08/31/crm-2011-form-errors-when-opening-non-customised-forms-object-doesn-t-support-property-or-method-form-load.aspx</a></li> <ul> <li>A RewriteModule problem may exist in IIS 7, and need to be reinstalled</li></ul></ul> <h3>Personal Upgrade Process</h3> <ul> <li>Avoiding more than one direct upgrade</li> <ul> <li>Never upgrade from CRM 3 to CRM 4 and then to CRM 2011; always make a clean break somewhere in the chain to avoid esoteric issues caused by upgrades daisy-chained this way</li></ul> <li>Wait for first adopters to uncover problems (sorry first adopters!)</li> <li>Virtual Machines!</li> <ul> <li>VMs are your IT friend. If you don’t think you can afford it, go grab <a href="http://downloads.vmware.com/d/info/datacenter_cloud_infrastructure/vmware_vsphere_hypervisor_esxi/5_0" target="_blank">VMWare ESXi</a>—it’s free, man</li></ul> <li>[IRAD] unsupported customizations</li> <ul> <li><strong>Identify</strong>: know where you’re currently using them, and what they do</li> <li><strong>Remove</strong>: eliminate them to avoid upgrade issues</li> <li><strong>Analyze</strong>: determine whether or not new functionality allows you to replace them with supported customizations/features</li> <li><strong>Deploy</strong>: after the upgrade, update and redeploy any unsupported customizations deemed necessary for business</li></ul></ul> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com1tag:blogger.com,1999:blog-5242498021352471451.post-37640919978448169632011-10-08T02:28:00.001-06:002011-10-08T02:28:05.068-06:00Farewell, Jim Glass<p>With <a href="http://blogs.msdn.com/b/jim_glass/archive/2011/10/06/goodbye-microsoft-hello-world.aspx">Jim’s recent announcement of his retirement from Microsoft</a>, I thought I’d make a little space here to immortalize my thoughts of a man I never got to meet in person, but dearly wished to.</p> <p>There’s something to be said about the Dynamics CRM community: chiefly that it is the most vibrant and active product community around any single Microsoft product.  Why? Two reasons:</p> <ol> <li>As I have long believed and been rewarded for such faith, it is simply the best product Microsoft has ever brought to market (that isn’t an Operating System); and</li> <li>Fantastic community leadership, fostering an open, engaging dialog between the users of the product and the experts that know it.</li> </ol> <p>Jim Glass is directly responsible for both.  There’s no objective way for me to quantify that, however, so take that declaration as the biased opinion of one happy CRM MVP.</p> <p>I’ve never known a CRM world without Jim, and long before I entered the MVP space, I met Jim on the battlegrounds we call the public CRM forums.  Jim was always watching, carefully moderating and steering the forum to productive ends.  He encouraged the MVPs, on a regular basis, to contribute and participate with the community at large—and the forums were just that.</p> <p>There is no mistaking the emptiness that I feel now that I know he’s gone, and I wait patiently for his successor to fill his space as best as possible (daunting though that may be).  Since I never had the opportunity to pay my respects and give my appreciation to Jim in person, I find myself obligated by duty to honor his legacy by applying myself to the forums in a way I know he would wish.</p> <p>Those who knew Jim understand the impact and the gravity his absence will generate.  Those who didn’t, may never understand what he did to improve their experience with CRM, the product or the community.  In some small way, I wish I could impart that feeling; but I doubt I have the raw ability to put in words what Jim has done, for me—for us.  I will miss him, and follow his social publications with great interest.</p> <p>Farewell, Jim. To have known you from afar, is better than to never have known you at all.</p> <blockquote> <p><em>“To leave, or not to leave--that is the question. <br />Whether ‘tis nobler in the mind to suffer <br />The pings and queries of MVP misfortune <br />Or to take charms against a sea of blogs <br />And by composing, mend them. To pry, to seek— <br />No more—and by seek to say we end <br />The madness, and the thousand natural questions <br />An MVP is heir to.”</em></p></blockquote> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com1tag:blogger.com,1999:blog-5242498021352471451.post-51773528583563651382011-09-27T20:58:00.001-06:002011-09-27T21:01:45.610-06:0060k Page Views!<p>When I first started this blog, I really didn’t expect it to take me anywhere. I just wanted a neat little place to post my code, a place that would follow me wherever I went and be a sounding board for whatever I thought (about CRM).</p> <p>This evening, while following up on my social activities (forum contributions, blog reading, and that Twitter thing), I discovered that the ticker on my page-view counter rolled past 60 thousand. A number I would never have expected. This comes on the tail of passing my first Microsoft Certification Exam. (I’m finally an MCP, too!)</p> <p>Now, I’m not one to relish in popularity. I’m a pretty shy and reserved person. So, the only thing I hope to take from this statistic is that I have hopefully helped many Dynamics CRM implementers and developers who have come here looking for help (or free code *wink*).</p> <p>If you have found value in this space, I’d love to hear about it. That kind of thing is what encourages me to contribute—and with more frequency.</p> <p>On a positive note, I may start posting more frequently in this space (and others) regarding some very exciting learning opportunities that are coming my way in the near future. There will be unique challenges that I’ll get to address with CRM, and my company, <a href="http://www.journeyteam.com" target="_blank">JourneyTEAM</a>, has given me motivation to contribute the value from my experiences with you, my audience.</p> <p>So, thank you for your readership. I hope I have given you useful and helpful information, and a better idea of how to squeeze great things from Dynamics CRM.</p> <p><a href="http://lh4.ggpht.com/-w7qZRiOaqAQ/ToKOFtIbT1I/AAAAAAAAAQ8/i1F9MvH_bNw/s1600-h/September%2525202011%252520Stats%25255B5%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="September 2011 Stats" border="0" alt="September 2011 Stats" src="http://lh6.ggpht.com/-of54SrhsXWg/ToKOGPpTPyI/AAAAAAAAARA/w61kpLqS9JM/September%2525202011%252520Stats_thumb%25255B3%25255D.png?imgmax=800" width="492" height="217"></a></p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com1tag:blogger.com,1999:blog-5242498021352471451.post-44189257724013814642011-09-17T06:12:00.001-06:002011-09-18T14:48:20.740-06:00Review: CRM 2011 Administration Bible<p>Publisher: <a href="http://www.wiley.com/WileyCDA/">Wiley</a> <br>Authors: <a href="http://www.linkedin.com/in/mattwittemann">Matt Wittemann</a>, <a href="http://www.linkedin.com/in/customerrelationshipmanagement">Geoff Ables</a> <br>CRM Entropy Rating (in Baked Goods): 3.1415926535897</p> <p>Matt, a fellow CRM MVP, sent me a copy of this book a long time ago, and I’ve pretty much only used it for reference material here and there until recently. I’ve read a handful of <a href="http://www.amazon.com/s/ref=nb_sb_noss?field-keywords=crm+4&url=search-alias%3Dstripbooks&x=0&y=0">CRM 4 books</a> in my day, and found a great deal of helpful information from them. The <a href="http://www.amazon.com/Microsoft-Dynamics-2011-Administration-Bible/dp/0470568143/ref=cm_cr_pr_pb_t">Microsoft Dynamics CRM 2011 Administration Bible</a> marks my first in-depth read relating to CRM 2011.</p> <p>The title of this book is both accurate and misleading—and I don’t mean from a theological standpoint. (Though I imagine, given the apologist forewords by Matt and Geoff, the word “God” was uttered on multiple occasions with various modifiers during its authoring.) This book is indeed a Bible in the sense that it combines a complete picture of CRM, from URL to SQL, from Form to Filter, and from Dialog to Migration. It really has it all.</p> <p>However, don’t let the word “Administration” throw you for a loop. This book isn’t geared specifically for administrators of any kind, and it doesn’t just cover administration. It’s so thoroughly educational on the core processes of CRM, I dare say that it is the first and last book you’ll need for Microsoft Dynamics CRM 2011 (see my “Bible” comment above). Matt and Geoff take special care to make every reader an Administrator. And that’s why the damn thing is so thick! (Caution: Ordering more than 3 of these books at a time involves <em>freight </em>charges.<sup>*</sup>)</p> <p>The machines with which this Bible was written have long surrendered their keyboards to a higher power. The material is dense and enriching not only for newcomers to the CRM experience, but for those arriving to CRM 2011 looking for what changed from the previous version—like myself. As with a religious text, you’ll find yourself engaged in the index or table of contents quite a bit, if you’re working with CRM already. But, you will find value throughout the areas you don’t think you need to read.</p> <p>This book will teach you all of the standard features that come with Dynamics CRM out-of-the-box, and then open your mind to the possibilities of custom enrichment. It wouldn’t be a book to <em>buy</em> if you’re only investigating Dynamics CRM (though it wouldn’t hurt to read); but it is an essential part of any CRM implementation, and its material is useful to every deployment and use of CRM that I can think of.</p> <p>So, from this digital pulpit, I preach from one Bible, and that is the <a href="http://www.amazon.com/Microsoft-Dynamics-2011-Administration-Bible/dp/0470568143/ref=cm_cr_pr_pb_t">Microsoft Dynamics CRM 2011 Administration Bible</a>! If you have Dynamics CRM, do yourself a favor and have this book, too.</p> <p><font size="1"><sup>*</sup> I’m kidding! But really, you do get more words for your dollar… and the most helpful ones to boot!</font></p> Dave Berryhttp://www.blogger.com/profile/00550842553228989698noreply@blogger.com0