<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0"><channel xml:base="https://thomasfaulkner.nz/"><title>Thomas Faulkner</title><description>Latest blog posts</description><a10:link href="https://thomasfaulkner.nz/" /><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2015/05/how-to:-update-plugin-assembly-via-api</guid><link>https://thomasfaulkner.nz/post/2015/05/how-to:-update-plugin-assembly-via-api</link><a10:author><a10:name /></a10:author><title>How To: Update Plugin Assembly Via API</title><description>&lt;p&gt;Here’s a quick and easy way to update a plugin assembly in CRM to give much quicker turn around when developing. Note: this will only work if the plugin is deployed to the database.&lt;/p&gt; &lt;p&gt;Plugin assemblies work just the same as all other entities in CRM, which means you can make API calls to retrieve, create or update them. While there is a bit of effort involved in creating new assembly records in CRM and all the associated plugins, steps, images etc. If you want all that to remain the same and to just simply update the deployed code, all you need to do is the following:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;var pluginAssembly = new Entity("pluginassembly")
{
  Id = new Guid(pluginAssemblyId),
  Attributes =
  {
    {"content", Convert.ToBase64String(File.ReadAllBytes(assemblyPath))}
  }
};&lt;/pre&gt;
&lt;p&gt;Where pluginAssemblyId is the id of the assembly you want to update, assemblyPath is the path to the assembly file on disk that you want to deploy and crmService is an authenticated OrganizationServiceProxy (see: &lt;a href="http://blog.thomasfaulkner.nz/post/2015/03/crm-organization-service-(re)authentication"&gt;my previous post&lt;/a&gt; to see how to initialise one)&lt;/p&gt;
&lt;p&gt;If you don’t know the id of the assembly, you can look it up via the name first:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;var pluginAssemblies = crmService.RetrieveMultiple(new QueryExpression("pluginassembly")
{
  Criteria = new FilterExpression
  {
    Conditions = {new ConditionExpression("name", ConditionOperator.Equal, name)}
  }
});
var pluginAssemblyId = pluginAssemblies.Entities[0].Id;&lt;/pre&gt;
&lt;p&gt;Assuming the plugin name is the same as the assembly file name, you could also just pull this from the path:&lt;/p&gt;&lt;pre class="brush: csharp"&gt;var name = Path.GetFileNameWithoutExtension(assemblyPath);&lt;/pre&gt;</description><pubDate>Wed, 20 May 2015 06:27:00 Z</pubDate><a10:updated>2015-05-20T06:28:19Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2015/04/updated-list-of-microsoft-crm-javascript-bookmarks</guid><link>https://thomasfaulkner.nz/post/2015/04/updated-list-of-microsoft-crm-javascript-bookmarks</link><a10:author><a10:name /></a10:author><title>Updated list of Microsoft CRM Javascript Bookmarks</title><description>&lt;p&gt;This is an updated list – to extend the original list I made in the post &lt;a href="http://blog.thomasfaulkner.nz/post/2014/05/microsoft-crm-javascript-bookmarks"&gt;here&lt;/a&gt; – of the Javascript bookmarks I have in my browsers, to make my life a bit easier as a power user in CRM. While the latest updates have made navigation a bit easier (especially with the addition of an advanced find button on all screens), I still find many of these links easier and quicker to use.&lt;/p&gt; &lt;p&gt;I have left the bookmarks unformatted because I am a bit lazy, but also so they can just be copied into a new bookmark url box without the new lines messing things up. This does mean that they don’t display so well here, so be warned.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;GodMode&lt;/strong&gt;: I picked this one (including the name) up somewhere along the way (sorry, I can’t find the original link to credit them with it), but tweaked it slightly. This essentially unlocks forms for you. It shows all hidden fields, unlocks all locked fields, clears all notifications and expands all tabs and sections. Use with caution as it can potentially circumvent client side controls and allow you to do things that users shouldn’t normally be able. However, anything important is actually being validated server side as well? Right? &lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20form=$("iframe").filter(function(){return%20$(this).css("visibility")=="visible"})[0].contentWindow;var%20attrs=form.Xrm.Page.data.entity.attributes.get();for(var%20i%20in%20attrs){attrs[i].setRequiredLevel("none")}var%20contrs=form.Xrm.Page.ui.controls.get();for(var%20i%20in%20contrs){try{contrs[i].setVisible(true);contrs[i].setDisabled(false);contrs[i].clearNotification()}catch(e){}}var%20tabs=form.Xrm.Page.ui.tabs.get();for(var%20i%20in%20tabs){tabs[i].setVisible(true);tabs[i].setDisplayState("expanded");var%20sects=tabs[i].sections.get();for(var%20i%20in%20sects){sects[i].setVisible(true)}}}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;ShowSchemaNames: &lt;/strong&gt;This does what it says on the tin: replaces all the field labels on the form with the schema names. This is useful as a developer when you need to know the name of the field to use in code and saves time instead of opening up the form or customisations.&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:function%20getFrame()%20{var%20$iframe%20=%20$('#crmContentPanel%20iframe:not([style*="visibility:%20hidden"])');if%20($iframe.length%20&amp;gt;%200%20&amp;amp;&amp;amp;%20$iframe[0].contentWindow.Xrm.Page.ui)%20{return%20$iframe[0].contentWindow;}else%20{return%20null;}}var%20frame%20=%20getFrame();if%20(frame%20==%20null)%20{alert('Please%20make%20sure%20you%20are%20on%20an%20entity%20form%20and%20try%20again.');}else%20{frame.Xrm.Page.ui.controls.forEach(function(a){a.setLabel(a.getName())});}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;GetUrl: &lt;/strong&gt;Pops up a dialog box with the URL of the current record in it. This gives you a quick way to grab a link to send to someone or open in a new window.&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20iframe%20=%20$("iframe").filter(function%20()%20{%20return%20($(this).css('visibility')%20==%20'visible')%20})[0];var%20url%20=%20iframe.contentWindow.Xrm.Page.context.getClientUrl()%20+%20"/main.aspx?pagetype=entityrecord&amp;amp;etn="%20+%20iframe.contentWindow.Xrm.Page.data.entity.getEntityName()%20+%20"&amp;amp;id="%20+%20iframe.contentWindow.Xrm.Page.data.entity.getId().slice(1,%20-1);if%20(window.prompt("URL:",%20url))%20{%20}}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;OpenProperties: &lt;/strong&gt;Opens the properties page that existed in CRM 2011, but isn’t accessible anymore. Gives you an easy way to see created/modified by/on etc.&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20frame%20=%20$("iframe").filter(function%20()%20{%20return%20($(this).css('visibility')%20==%20'visible')%20});%20var%20id%20=%20frame[0].contentWindow.Xrm.Page.data.entity.getId();%20var%20etc%20=%20frame[0].contentWindow.Xrm.Page.context.getQueryStringParameters().etc;%20frame[0].contentWindow.Mscrm.RibbonActions.openFormProperties(id,%20etc);}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;OpenById: &lt;/strong&gt;Know the schema name and Id of a record that you want to view? Enter those two bits of info in the dialogs that pop up and away you go. &lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20iframe%20=%20$("iframe").filter(function%20()%20{%20return%20($(this).css('visibility')%20==%20'visible')%20})[0];var%20entity%20=%20window.prompt("Entity:");var%20id%20=%20window.prompt("Id:");var%20url%20=%20iframe.contentWindow.Xrm.Page.context.getClientUrl()%20+%20"/main.aspx?pagetype=entityrecord&amp;amp;etn="%20+%20entity%20+%20"&amp;amp;id="%20+%20id;window.location%20=%20url;}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;GoTo…&lt;/strong&gt; (the following navigate you to the specified section within the CRM organization you are currently looking at.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Accounts&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Solution/home_solution.aspx?etc=1&amp;amp;sitemappath=SFA|Customers|nav_accts";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);%20void%20(0)}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Contacts&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Solution/home_solution.aspx?etc=2&amp;amp;sitemappath=SFA|Customers|nav_conts";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Opportunities&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Solution/home_solution.aspx?etc=3&amp;amp;sitemappath=SFA|SFA|nav_oppts";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);%20void%20(0)}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Processes&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Solution/home_solution.aspx?etc=4703&amp;amp;sitemappath=Settings|ProcessCenter|nav_workflow";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);%20void%20(0)}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Administration&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Admin/admin.aspx?sitemappath=Settings|System_Setting|nav_administration";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);%20void%20(0)}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SystemJobs&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Solution/home_solution.aspx?etc=4700&amp;amp;sitemappath=Settings|System_Setting|nav_systemjobs";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);%20void%20(0)}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Customizations&lt;/strong&gt;&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:%20try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/systemcustomization/systemcustomization.aspx?pagemode=iframe&amp;amp;sitemappath=Settings%7cCustomizations%7cnav_syscust";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Users &lt;/strong&gt;(2013 – where Users is under the Administration section in CRM)&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:try{var%20o%20=%20new%20Object();%20o.uri%20=%20"/tools/Admin/admin.aspx?sitemappath=Settings|System_Setting|nav_administration&amp;amp;pagemode=iframe&amp;amp;pid=07&amp;amp;web=true";%20window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Users&lt;/strong&gt; (2015 – where Users is under the Security section in CRM)&lt;/p&gt;&lt;pre class="brush: js"&gt;javascript:try{var%20o%20=%20new%20Object();o.uri%20=%20"/tools/AdminSecurity/adminsecurity_area.aspx?sitemappath=Settings|System_Setting|nav_security&amp;amp;pagemode=iframe&amp;amp;pid=06&amp;amp;web=true";window.top.document.getElementById("navBar").control.raiseNavigateRequest(o);}catch(e){}&lt;/pre&gt;</description><pubDate>Sun, 26 Apr 2015 03:34:34 Z</pubDate><a10:updated>2015-04-26T03:34:34Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2015/03/crm-service-endpoint-certificate</guid><link>https://thomasfaulkner.nz/post/2015/03/crm-service-endpoint-certificate</link><a10:author><a10:name /></a10:author><title>CRM Service Endpoint Certificate</title><description>&lt;p&gt;This post follows on from my &lt;a href="http://blog.thomasfaulkner.nz/post/2014/08/crm-and-microsoft-azure-service-bus" target="_blank"&gt;post&lt;/a&gt; last year about registering Service Endpoints in CRM to send messages to an Azure Service Bus.&lt;/p&gt; &lt;p&gt;If you make use of this functionality and were not aware of the pending certificate expiry for CRM you may have had the unpleasant experience of the messages being sent to the service bus queue (or topic etc) failing in the last week or so (as of 7 March 2015). Basically, for security enhancements the existing certificate expired and a new one was issued to authenticate against the Azure service.&lt;/p&gt; &lt;p&gt;All the information you need is here: &lt;a title="http://support.microsoft.com/en-us/kb/2836034" href="http://support.microsoft.com/en-us/kb/2836034"&gt;http://support.microsoft.com/en-us/kb/2836034&lt;/a&gt;&lt;/p&gt; &lt;p&gt;To summarise (and in case that link no longer works): If I was organised and got this post out early, the recommendation would be to login to the access control page for your service bus namespace (&lt;u&gt;https://&amp;lt;servicenamespace&amp;gt;-sb.accesscontrol.windows.net/v2/mgmt/web&lt;/u&gt;&lt;font color="#000000"&gt;)&lt;/font&gt; and under Service Settings –&amp;gt; Service Identities add the new certificate for your region (this can be downloaded from your CRM instance under Settings –&amp;gt; Customizations –&amp;gt; Developer Resources or from the links in the article link above). By having the two certificates installed side by side, you would have been able to have continuous service as they transitioned over and could then remove the old certificate at your own time. Now that it is past the expiry date, if you do not have the new certificate installed you should get this installed ASAP and can just replace the existing one. Once the new certificate is installed (give or take a few minutes for the change to propagate), you should be all good to go again.&lt;/p&gt; &lt;p&gt;So there we go. As with a lot of certificate expiry related issues, there is little to no notification that they are about to expire, so is something that as system administrators we need to be aware of and manage accordingly. We now have a few years to get ready for the new certificate here to expire and need changing again.&lt;/p&gt;</description><pubDate>Mon, 16 Mar 2015 09:00:26 Z</pubDate><a10:updated>2015-03-16T09:00:26Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2015/03/crm-organization-service-(re)authentication</guid><link>https://thomasfaulkner.nz/post/2015/03/crm-organization-service-(re)authentication</link><a10:author><a10:name /></a10:author><title>CRM Organization Service (Re)Authentication</title><description>&lt;p&gt;If you need to create a long running application to interact with the Microsoft CRM web services – for example, something to perform data migration or integration tasks – you need to be aware that, like all good things, web service connections do not last forever. &lt;/p&gt; &lt;p&gt;Note: the following uses example c# code and the CRM SDK libraries to connect to CRM Online. &lt;/p&gt; &lt;p&gt;First up, we need an instance of OrganizationServiceProxy. This can be created like so:&lt;/p&gt;&lt;pre&gt;var uri = new Uri(string.Format("https://{0}.crm.dynamics.com/XRMServices/2011/Organization.svc", orgName));
var clientCredentials = new ClientCredentials();
clientCredentials.UserName.UserName = username;
clientCredentials.UserName.Password = password;
var deviceCredentials = DeviceIdManager.LoadOrRegisterDevice(); //from SDK: SampleCode\CS\HelperCode\DeviceIdManager.cs 
var organizationServiceProxy = new OrganizationServiceProxy(uri, null, clientCredentials, deviceCredentials);&lt;/pre&gt;
&lt;p&gt;Now, if you check the IsAuthenticated property on this, you will see that it is false. It is not until you actually use the service to do something that it actually gets authenticated. This lazy authenticating can be useful and saves some time when initialising the OrganizationServiceProxy object, as in the above sample. However, if you made a mistake with the credentials you won't actually know at this point, since it isn't until the authentication actually occurs that the provided credentials are checked. This could be an issue if you don't use the service straight away and don't want to wait until it is needed for you (or the end user of your application) to learn that the provided credentials are incorrect.&lt;/p&gt;
&lt;p&gt;More importantly, it also means that when the first request is made there is an overhead to it, because it first has to authenticate and only then can it process the request. If you are creating an application that is waiting for user input or another service to call it, it may be better to take the hit straight up so you can then return responses as quickly as possible to the end user.&lt;/p&gt;
&lt;p&gt;Thankfully, this is easily resolved: explicitly authenticate the service after creating it:&lt;/p&gt;&lt;pre&gt;organizationServiceProxy.Authenticate();&lt;/pre&gt;
&lt;p&gt;So now we can get an authenticated connection but, getting back to my initial point, this will not stay so indefinitely. An authenticated OrganizationServiceProxy (against CRM Online at least), has a lifetime of 8 hours, and after this point any attempt to use it to communicate with CRM will result in security exceptions. This is easy enough to work around. Simply add a check before using it to check if the expiry time is coming up and if so call authenticate, which will take a little while, and then carry on with what you were doing. &lt;/p&gt;
&lt;p&gt;Rather than trying to add this check before every request to the OrganizationServiceProxy, a better way to do this is to create a subclass of OrganizationServiceProxy and override ValidateAuthentication. This gets called before any other request gets processed, which allows you to write this check in one place and forget about. In this method we, simple add a check to see if the security token is about to expire and if so re-authenticate the service. Like so:&lt;/p&gt;&lt;pre&gt;using System;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk.Client;

namespace Demo
{
    public class CrmService : OrganizationServiceProxy
    {
        public CrmService(Uri uri, Uri homeRealmUri, ClientCredentials clientCredentials, ClientCredentials deviceCredentials)
            : base(uri, homeRealmUri, clientCredentials, deviceCredentials)
        {
            Authenticate();
        }

        protected override void ValidateAuthentication()
        {
            EnsureAuthentication();
            base.ValidateAuthentication();
        }

        private void EnsureAuthentication()
        {
            if ((SecurityTokenResponse != null) &amp;amp;&amp;amp;
                (DateTime.UtcNow.Add(TimeSpan.FromMinutes(30)) &amp;gt;= SecurityTokenResponse.Response.Lifetime.Expires))
            {
                Authenticate();
            }
        }
    }
}&lt;/pre&gt;
&lt;p&gt;In the above example, I also added Authenticate() in the constructor so when you create a new instance of this it comes pre authenticated and you are good to go and use this exactly as you would the standard OrganizationServiceProxy.&lt;/p&gt;</description><pubDate>Fri, 06 Mar 2015 00:48:00 Z</pubDate><a10:updated>2018-10-14T00:50:11Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2014/09/upgrading-custom-workflow-assemblies</guid><link>https://thomasfaulkner.nz/post/2014/09/upgrading-custom-workflow-assemblies</link><a10:author><a10:name /></a10:author><title>Upgrading Custom Workflow Assemblies</title><description>&lt;p&gt;I do not particularly like workflows in CRM. Custom workflows in particular. While I concede there are cases where workflows in CRM can work and that certain custom workflows are useful to add additional capabilities to something a power user can control, from my (albeit rather limited) experience, they are often used (or abused?) outside these situations. Especially where a plug-in would be much better suited. &lt;p&gt;Unfortunately, I have ended up with a project full of them. With over a hundred different processes and 22 custom workflow assemblies referenced by more than 50 them (some referencing multiple), the system is not my perspective of ideal. Regardless, it has fallen to me to upgrade this CRM4 code base and start to get the system in shape for a future move to CRM2013.&amp;nbsp; &lt;p&gt;In preparation for this upgrade I was testing the approach to upgrade the workflows and referenced libraries from .NET 3.5, 3 or earlier and replacing references to CRM4 libraries (i.e. Microsoft.Crm.Sdk) with CRM2011 libraries (i.e. Microsoft.Xrm.Sdk etc) and everything that comes with that (replacing CRM4 types: CrmBoolean, CrmNumber, Lookup, DynamicEntity etc). My initial finding was that an in place upgrade of the code would break a deployed workflow. When you deployed the new assembly it seemed to be fine, however new instances of the workflow will fail. If you try deactivate the workflow and edit it you see this: &lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/72fb6952-78fb-40f3-92ff-92d37421cb50.png"&gt;&lt;img title="5" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="5" src="http://thomasf.azurewebsites.net/posts/files/d9fc8bb0-04fa-4fed-85ab-a80387823372.png" width="801" height="167"&gt;&lt;/a&gt;  &lt;p&gt;All the steps that reference the custom workflow show an error message and you can't open them to edit or delete them. Other than the error icon, it doesn't provide much information as to what is wrong. To have a look at what was going on, I exported the workflows in a solution and had a look at the XAML. Turns out the workflow itself has references to the input field types and being originally CRM4 based, these are the old CRM types, for example CrmNumber. It seems that this doesn't reconcile when CRM sees the new code that we deployed so it gives up.&amp;nbsp; &lt;p&gt;The first fix that came to mind here was to update the XAML to fix these references. This is a bit of a pain, but only really another set of find and replaces. However, it turns out there is a much simpler fix within CRM. All you need to do is open up the workflow (deactivate it if it is active) and then open the properties for the custom activities input (the first Set Properties button in the screen shot above). This will show the inputs for the custom workflow, which should all look the same as before. You don't actually need to change anything here (unless you want to of course), so just save and close out. Again, it looks like nothing has changed and the errors are still there, but hit save and close again. Now just open it up again and all of a sudden the errors are gone. &lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/feae636b-3469-431c-99be-a0b4c64be536.png"&gt;&lt;img title="6" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="6" src="http://thomasf.azurewebsites.net/posts/files/7d035675-1dbc-4c35-99db-c86e87ade94e.png" width="811" height="182"&gt;&lt;/a&gt;  &lt;p&gt;How easy is that! Simply saving the input parameters must trigger CRM to check and update all the parameter types for the workflow, which means the output parameters now match what is expected and the workflow can happily be activated and run. You can confirm this by exporting the workflow again and looking at the XAML.&lt;/p&gt; &lt;p&gt;Awesome, so it seemed like my workflow headaches were going away. That is, until I realised that unlike CRM2011 workflow assemblies, CRM4 did not require the assembly to be signed… and if you sign an assembly it changes the strong name, which means it will not let you provide it as an update for the deployed code, so the above fix was not going to be enough for everything that I was facing... However, how I went about fixing that is a story for another day.&lt;/p&gt;</description><pubDate>Thu, 04 Sep 2014 05:00:00 Z</pubDate><a10:updated>2014-09-04T09:51:50Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2014/08/crm-and-microsoft-azure-service-bus</guid><link>https://thomasfaulkner.nz/post/2014/08/crm-and-microsoft-azure-service-bus</link><a10:author><a10:name /></a10:author><title>CRM and Microsoft Azure Service Bus</title><description>&lt;p&gt;Do you know what the selected option below is:&lt;/p&gt; &lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/cc220a58-c222-449a-94e2-5d06fd771dfd.png"&gt;&lt;img title="Untitled" 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="Untitled" src="http://thomasf.azurewebsites.net/posts/files/c2a9f495-487d-4a5c-99f5-ff0539a54c95.png" width="244" height="103"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Until I starting playing with Azure and discovered that CRM has built in functionality to send messages to the Azure Service Bus (i.e. this) I didn’t even give it a moments thought. This option in the CRM plugin registration tool is the entry point to getting your solution talking to Azure and opening up some new and exciting opportunities.&lt;/p&gt; &lt;p&gt;In this post, I will quickly run through how to register a new service endpoint, which is a little bit more complex then just clicking the highlighted option. This will include how to create the service bus in Azure. In a later post I will discuss what you can do with this once it is up and running.&lt;/p&gt; &lt;p&gt;First up, you need to create the service bus in Azure. If you don’t already have an Azure subscription jump on to &lt;a title="http://azure.microsoft.com/" href="http://azure.microsoft.com/"&gt;azure.microsoft.com&lt;/a&gt; and sign up for a free trial. For this example we will use a Queue, but there are several other options that you can use as well, each provides different capabilities. I won’t screen shot every step, but this is a simple case (as of the time of this post – Azure may change all of this in the future) of clicking on the following:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;+ NEW  &lt;li&gt;APP SERVICES  &lt;li&gt;SERVICE BUS  &lt;li&gt;QUEUE  &lt;li&gt;CUSTOM CREATE  &lt;li&gt;Specify Queue Name, Region and either use existing or create a new namespace  &lt;li&gt;Configure the queue with the options you want.  &lt;li&gt;&lt;strong&gt;&lt;em&gt;Make sure Enable Partitioning is&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;&lt;strong&gt;unticked&lt;/strong&gt;&lt;/em&gt;, otherwise you won’t be able to use it with CRM  &lt;li&gt;Click the tick icon down the button to accept&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Azure will then go away and in a minute or two finish creating and activating your service bus. &lt;/p&gt; &lt;p&gt;Next up, we need to get the connection information to plug into CRM and get it talking to your new service bus. To get this information you need to select the service bus (note: there is a difference between selecting the service bus and going into it and seeing the queues, you need to click on a column other than the Namespace Name to select it) and click CONNECTION INFORMATION at the bottom of your screen. All you need from this screen is the default key and they provide a copy button beside it if you are too lazy to select and copy it yourself.&lt;/p&gt; &lt;p&gt;Now we can get back to that initial image. Connect the plugin registration tool to your CRM organisation and hit Register New Service End Point:&lt;/p&gt; &lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/235b9294-060e-494d-a366-bcf99fa8a959.png"&gt;&lt;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://thomasf.azurewebsites.net/posts/files/72c5271d-8ca7-4276-a4b6-b624aaed1cf7.png" width="595" height="376"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this screen fill in:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Name: the name you want to call this connection  &lt;li&gt;Description: an optional description of what this is for &lt;li&gt;Solution Namespace: the name of the service bus namespace you created or used in Azure above  &lt;li&gt;Path: the name of the queue you created above  &lt;li&gt;Contract: Queue (for this example at least)  &lt;li&gt;Claim: None  &lt;li&gt;Federated Mode: Unticked&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Then click Save &amp;amp; Configure ACS and you should see this screen:&lt;/p&gt; &lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/306b2abd-9beb-4aca-a56e-03915d9ebdab.png"&gt;&lt;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://thomasf.azurewebsites.net/posts/files/4d7245e6-5d27-47e9-9b82-e98d137d4814.png" width="729" height="590"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Fill in:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Management Key: The default key you copied from the connection information screen in Azure earlier&amp;nbsp; &lt;li&gt;Certificate File: In CRM browse to Customizations, Developer Resources (or just click the link in the dialog shown above), download the certificate and browse to where you downloaded it &lt;li&gt;Issuer Name: You will find this in the same place as the certificate. Should be something along the lines of crm.dynamics.com or crm5.dynamics.com depending on your region.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Then click Configure ACS and if everything goes well, close the dialog, save and verify, save again and you are done. You should now have a brand new service endpoint configured in CRM. This will not do anything yet, but in my next post I will show you some things you can try. The CRM SDK is also a great source of sample code to carry on from this.&lt;/p&gt;</description><pubDate>Mon, 04 Aug 2014 07:00:00 Z</pubDate><a10:updated>2014-08-04T07:00:12Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2014/05/microsoft-crm-javascript-bookmarks</guid><link>https://thomasfaulkner.nz/post/2014/05/microsoft-crm-javascript-bookmarks</link><a10:author><a10:name /></a10:author><title>Microsoft CRM Javascript Bookmarks</title><description>&lt;p&gt;&lt;font size="3"&gt;Note: The following is based/extended from the recent blog entry by Jared Johnson over at Magnetism Solutions:&lt;/font&gt; &lt;a href="http://www.magnetismsolutions.com/blog/jaredjohnson/2014/05/14/bookmarklets-to-aid-microsoft-dynamics-crm-2013-development" target="_blank"&gt;&lt;font size="3"&gt;Bookmarklets to aid Microsoft Dynamics CRM 2013 Development&lt;/font&gt;&lt;/a&gt; &lt;font size="3"&gt;– Thanks for the tip&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;Navigating around CRM, in particular the new user interface in CRM2013, can be slightly annoying at times. Especially for developers and customisers who are not exactly using the system as it is designed for end users. As power users we often need to get to parts of the system that are behind the scenes (such as customisations and solutions) or get information out of the system that end users don’t need to know or care about (such as record GUIDs). In the past, I have achieved this by making bookmarks to solutions (i.e. absolute URL to a solution for a specific organisation, which is useless once I am no longer working on that project) or by opening up the developer tools in my browser and writing some javascript to tease out the information I need. However, finding the id of a record by typing “Xrm.Page.data.entity.getId()” over and over again, fixing typos, dealing with how each browser handles the iFrames in CRM and all the other nuances involved can get very tedious.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;In the post linked above, Jared suggests a better way: using javascript in bookmark (or&lt;/font&gt; &lt;a href="http://en.wikipedia.org/wiki/Bookmarklet" target="_blank"&gt;&lt;font size="3"&gt;Bookmarklets&lt;/font&gt;&lt;/a&gt;&lt;font size="3"&gt;). Below is a list of the bookmarklets I have added to my virtual toolkit, based on his post and some additions of my own. These work (on my machine) in IE, Firefox and Chrome and on any CRM organisation I have tried, but I don’t provide any guarantees. &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;Disclaimer: these are not necessarily supported approaches to interact with CRM so there is always the potential for future updates to break them or cause them to behave differently. It is recommended you understand what they are doing before you copy, paste and use them blindly.&lt;/font&gt;&lt;/p&gt; &lt;h2&gt;GetId()&lt;/h2&gt;&lt;pre class="brush: js"&gt;javascript: try{if (window.prompt("ID:", $("iframe").filter(function () { return ($(this).css('visibility') == 'visible') })[0].contentWindow.Xrm.Page.data.entity.getId().slice(1, -1))) { }}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;font size="3"&gt;Pops a dialog box with the id of the current record (braces removed) selected for you to easily copy and do whatever you need with it.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/781bbf07-2462-467e-80db-982a07ec3972.png"&gt;&lt;img title="Capture" 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="Capture" src="http://thomasf.azurewebsites.net/posts/files/0a178b1d-799d-4936-8d2f-9ab09b55dcee.png" width="339" height="159"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;h2&gt;RefreshData()&lt;/h2&gt;&lt;pre class="brush: js"&gt;javascript:try{$("iframe").filter(function () { return ($(this).css('visibility') == 'visible') })[0].contentWindow.Xrm.Page.data.refresh()}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;font size="3"&gt;Reloads the data on the current form, without refreshing the whole page so is much quicker. Useful if you know the data on the server has changed and you want to see this reflected in your browser and would rather not have the whole page reload and break back history, trigger code etc.&lt;/font&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/a853d602-c8b3-4302-b7a9-35aad134449a.png"&gt;&lt;img title="Capture2" 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="Capture2" src="http://thomasf.azurewebsites.net/posts/files/05e3cb58-5db8-44dd-a0e2-99840b4a2e2b.png" width="244" height="122"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h2&gt;OpenAdvancedFind()&lt;/h2&gt;&lt;pre class="brush: js"&gt;javascript:try{open($("iframe").filter(function () { return ($(this).css('visibility') == 'visible') })[0].contentWindow.Xrm.Page.context.getClientUrl() + "/main.aspx?pagetype=advancedfind")}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;font size="3"&gt;Opens advanced find for the current organisation in a new window/tab. Useful for when you are on a record or other page within CRM where Microsoft has decided an advanced find button isn’t necessary.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/ad09513c-618b-466e-ad51-c62b3a7e6b6f.png"&gt;&lt;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://thomasf.azurewebsites.net/posts/files/0dcb90c2-f9af-479d-a4a4-871f331ca0dc.png" width="796" height="252"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;GoToSolutions()&lt;/h2&gt;&lt;pre class="brush: js"&gt;javascript: try{var o = new Object(); o.uri = "/tools/Solution/home_solution.aspx?etc=7100&amp;amp;sitemappath=Settings|Customizations|nav_solution"; window.top.document.getElementById("navBar").control.raiseNavigateRequest(o); void (0)}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;font size="3"&gt;Navigates you to Settings &amp;gt; Solutions. Note: the back button will work from here and take you back to the previous page. This should be self explanatory and saves a few clicks. The code above should be easy to modify to navigate somewhere else.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://thomasf.azurewebsites.net/posts/files/1629d942-898b-4dc2-b954-ec11bbdb3ab0.png"&gt;&lt;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://thomasf.azurewebsites.net/posts/files/d662afbb-bb1f-4205-b103-afeb7bf0cb64.png" width="472" height="249"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;OpenDefaultSolution()&lt;/h2&gt;&lt;pre class="brush: js"&gt;javascript:try{open($("iframe").filter(function () { return ($(this).css('visibility') == 'visible') })[0].contentWindow.Xrm.Page.context.getClientUrl() + "/tools/solution/edit.aspx?id=FD140AAF-4DF4-11DD-BD17-0019B9312238")}catch(e){}&lt;/pre&gt;
&lt;p&gt;&lt;font size="3"&gt;Opens a new window/tab with the default solution of the organisation for you to view or customise. This script dynamically creates the URL for the default solution based on the client URL and the fact that the default solution has a the same ID for all CRM organisations (see: &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/gg328257.aspx" target="_blank"&gt;&lt;font size="3"&gt;Constant SolutionId Values&lt;/font&gt;&lt;/a&gt;&lt;font size="3"&gt;).&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="3"&gt;That is all I have for now, but I’m sure that there are many other ideas out there on how to leverage this. I will most likely find others myself as I use these and think about it further, particularly around the raiseNavigateRequest method. If so, a follow up to this post will be in order.&lt;/font&gt;&lt;/p&gt;</description><pubDate>Sun, 25 May 2014 06:21:00 Z</pubDate><a10:updated>2015-02-25T06:30:48Z</a10:updated></item><item><guid isPermaLink="true">https://thomasfaulkner.nz/post/2014/05/crm-developer-toolkit-delete-asyncoperation-if-statuscode--successful</guid><link>https://thomasfaulkner.nz/post/2014/05/crm-developer-toolkit-delete-asyncoperation-if-statuscode--successful</link><a10:author><a10:name /></a10:author><title>CRM Developer Toolkit: Delete AsyncOperation if StatusCode = Successful</title><description>&lt;p&gt;To set the scene, say you are developing a solution for CRM2013 using the &lt;a href="http://msdn.microsoft.com/en-us/library/hh372957.aspx" target="_blank"&gt;Developer Toolkit for Microsoft Dynamics CRM&lt;/a&gt; in Visual Studio and wanting to create a asynchronous plugin step. Easy right? Open CRM Explorer, find the entity, add a plugin, fill in the details, set it to run asynchronously and you are away. However, those of you that have used the plugin registration tool will know that there is a pretty handy option when &lt;a href="http://msdn.microsoft.com/en-us/library/hh237515.aspx#bkmk_RegStep" target="_blank"&gt;Registering a Step&lt;/a&gt; that lets you tell CRM to Delete AsyncOperation (i.e. system jobs) if the StatusCode = Successful:&lt;/p&gt; &lt;p&gt;&lt;img alt="Register New Step dialog" src="http://i.msdn.microsoft.com/dynimg/IC504279.png"&gt;&lt;/p&gt; &lt;p&gt;This is great because it means your system jobs table doesn’t get clogged up with entries when things are going fine. Instead it just tracks when you probably need to look into something. So how do you go about doing this in Visual Studio?&lt;/p&gt; &lt;p&gt;I was in this situation this week and found (let me know if I missed something obvious here) that this isn’t an option using the UI for the developer kit and there is no documentation (that I can find, nothing in the SDK and Google didn’t help me) on how to set this. I considered giving up and having this as an extra step to manually do after deploying the solution, which would be a pain, but decided to spend a bit more time and dig deeper. I decompiled the assembly for the developer toolkit (using dotpeek for those interested) and found that this is a supported, but not advertised option for the step in the RegisterFile.crmregister xml file within the CRMPackage project. All you need to do is add AsyncAutoDelete="true" attribute to the asynchronous step tags(s) in the XML, deploy and you are away laughing.&lt;/p&gt; &lt;p&gt;For example, your RegisterFile.crmregister will end up looking something like this:&lt;/p&gt;&lt;pre class="brush: xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;Register xmlns:xsi="&lt;a href="http://www.w3.org/2001/XMLSchema-instance&amp;quot;"&gt;http://www.w3.org/2001/XMLSchema-instance"&lt;/a&gt; xmlns:xsd="&lt;a href="http://www.w3.org/2001/XMLSchema&amp;quot;"&gt;http://www.w3.org/2001/XMLSchema"&lt;/a&gt; xmlns="&lt;a href="http://schemas.microsoft.com/crm/2011/tools/pluginregistration&amp;quot;"&gt;http://schemas.microsoft.com/crm/2011/tools/pluginregistration"&lt;/a&gt;&amp;gt;
   &amp;lt;Solutions&amp;gt;
       &amp;lt;Solution Assembly="Plugins.dll" Id="2318c739-68d9-d896-8cf1-6c3be5a8c238" IsolationMode="Sandbox" SourceType="Database"&amp;gt;
           &amp;lt;PluginTypes&amp;gt;
               &amp;lt;Plugin Description="Contact Plug-in" FriendlyName="ContactPlugin" Name="Plugins.ContactPlugin" Id="2618c739-68d9-d896-8cf1-6c3be5a8c238" TypeName="Plugins.ContactPlugin"&amp;gt;
                   &amp;lt;Steps&amp;gt;
                       &amp;lt;clear /&amp;gt;
                       &amp;lt;Step AsyncAutoDelete="true" CustomConfiguration="" Name="Plugins.ContactPlugin.PostContactUpdate" Description="Post-Operation of Contact Update" Id="92a843f0-68d9-d896-8cf1-6c3be5a8c238" MessageName="Update" Mode="Asynchronous" PrimaryEntityName="contact" Rank="1" SecureConfiguration="" Stage="PostOutsideTransaction" SupportedDeployment="ServerOnly"&amp;gt;
                           &amp;lt;Images /&amp;gt;
                       &amp;lt;/Step&amp;gt;
                   &amp;lt;/Steps&amp;gt;
               &amp;lt;/Plugin&amp;gt;
           &amp;lt;/PluginTypes&amp;gt;
       &amp;lt;/Solution&amp;gt;
   &amp;lt;/Solutions&amp;gt;
   &amp;lt;XamlWorkflows /&amp;gt;
&amp;lt;/Register&amp;gt;&lt;/pre&gt;
&lt;p&gt;While it would be nice to achieve this from the UI, something we might see in a future update, this is at least a pretty simple solution to work with for now.&lt;/p&gt;</description><pubDate>Sat, 24 May 2014 09:30:00 Z</pubDate><a10:updated>2015-02-25T09:32:31Z</a10:updated></item></channel></rss>