Over the years, this blog has been about many different things related to software development with Microsoft technologies. Since my current role focuses on PowerApps & Flow, that's what it's primarily about right now.
“I want to use Erwin [or Visio or Visual Studio or…] to graphically design the CRM entity model, then have the actual CRM entities generated off of the tool I used to design the entities.”
While I am not aware of a direct way to do this with any ERD tools, there is a multi-step process you can use as long as your ERD designer can generate a SQL or Access database:
Use your ERD designer to model your entities, fields and relationships
Generate a SQL or Access database from the designer
Of course, you’ll need to make sure you don’t pick data types in your diagram that the xrmspeedy tool can’t translate to CRM types, but this approach can be used as a productivity enhancement to those who prefer to diagram out their entities and generated them. Since this is an open source tool, you might consider contributing feedback if you have ideas for improvement. After a little trial and error, I’ve found I get value out of using Visual Studio’s Entity Framework Designer plus this tool when brainstorming data models and building POCs. Your Mileage May Vary (YMMV).
“I love early bound code because of compile time checking, LINQ query enablement, etc. I want to batch update a bunch of records, but OrganizationServiceContext.SaveChanges() executes under the hood as one web service call per entity. How do I batch update? Also, how do I make sure that only the fields I change are updated?”
The answer is that you basically have to combine your crmsvcutil.exe generated code with ExecuteMultipleResults. Here’s an example:
var conn = CrmConnection.Parse("USE A VALID connection string using appropriate format documented at https://msdn.microsoft.com/en-us/library/jj602970.aspx");
var ctx = new marcsctest1Context(new OrganizationService(conn));
// NOTE: The query below uses LINQ projection. The CRM LINQ provider will translate this to a query that only returns ID & Name
var query =
from a in ctx.AccountSet
select new Account
{
Id = a.Id,
Name = a.Name
};
var executeMultipleRequest = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings(){
ContinueOnError = false,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
foreach (var account in query)
{
account.Name += " - Updated";
//UpdateObject is required to set the EntityState to Changed because it is readonly through crmsvcutil generated entities
I’ve been a longtime fan of LINQPad (www.linqpad.net) as a general purpose tool for executing LINQ queries with various LINQ enabled technologies as well as a general purpose scratchpad for testing out .NET code without having to fire up Visual Studio. I’ve already blogged about how to use LINQPad to work with the CRM Online SOAP service:
One thing that may not be obvious is how to use LINQPad to query the OData service that comes with Dynamics CRM Online. Using the same basic concept that I showed with the SOAP service, I created a video walkthrough of how to interact with the OData service from LINQPad:
Here’s the LINQPad starter code I showed in the video:
var clientId = "[YOUR_CLIENT_ID]";
var resource = "https://[YOUR_INSTANCE].crm.dynamics.com";
var redirectUri = new Uri("http://linqpad"); //replace with your redirect uri
var authContext = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize", false);
var authResult = authContext.AcquireToken(resource, clientId, redirectUri, PromptBehavior.Auto);
Util.ClearResults();
var ctx = new marcsctest1Context(new Uri(resource + "/XRMServices/2011/OrganizationData.svc/"));
One of the things I did, after creating the video, was to write a reusable helper method in the LINQPad MyExtensions class so I can reuse the code to get the access token across multiple LINQPad query sessions. Here’s the code for the extension:
void Main()
{
// Write code to test your extensions here. Press F5 to compile and run.
}
publicstaticclass MyExtensions
{
// Write custom extension methods here. They will be available to all queries.
staticstring LINQPadAccessToken = null;
publicstaticstring GetAccessToken()
{
if (LINQPadAccessToken != null)
{
return LINQPadAccessToken;
}
var clientId = "[YOUR_CLIENT_ID]";
var resource = "https://[YOUR_INSTANCE].crm.dynamics.com";
var redirectUri = new Uri("http://linqpad"); //your redirect uri
var authContext = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize", false);
var authResult = authContext.AcquireToken(resource, clientId, redirectUri, PromptBehavior.Auto);
Util.ClearResults();
LINQPadAccessToken = authResult.AccessToken;
return LINQPadAccessToken;
}
}
Here’s a version of the code in my query tab that is simplified, after writing and leveraging the helper method:
var ctx = new marcsctest1Context(
new Uri("https://[YOUR_INSTANCE].crm.dynamics.com/XRMServices/2011/OrganizationData.svc/")
Note the call to MyExtensions.GetAccessToken() above. You could obviously refactor the GetAccessToken() method more to make it even more reusable, but I will leave that as an exercise for you.
This approach will become even more powerful once Dynamics CRM introduces the new OData v4 service endpoint:
As I mention in the video, once that happens, you’ll want to perform the codgen with the OData Client Code Generator instead of “Add Service Reference”:
CRM Online based solutions often run across the broader Microsoft Cloud, not just CRM Online alone. As they say, a picture is worth a thousand words. So here’s a picture that hits home this point at a high level.
To help people get started trying this environment out, I’ve created a video that walks you through setting up a trial for CRM Online, Office 365, and Microsoft Azure where all the services are provisioned for Single Sign On (SSO) under a single Azure Active Directory tenant and provide shared administration.
Debugging plugins in CRM Online just got a lot better with the latest version of the plugin registration tool that ships with CRM 2015. In the video below, I walk you through how to debug CRM Online plugins using Visual Studio.
Hear from Jujhar Singh, General Manager of Program Management for Microsoft Dynamics CRM, about why you should be a part of the Microsoft Dynamics Technical Conference. Equal parts education, networking, and fun, the Microsoft Dynamics Technical Conference brings together Microsoft Dynamics CRM professional and developer communities in a technical readiness experience designed to inspire you and help you take your business further. This is our first-ever such event for Microsoft Dynamics CRM partners. Don’t miss it! We want to see you there!
Time is running out: Register today for the Microsoft Dynamics Technical Conference! Your conference pass—priced at $1,595—gives you access to keynotes, general and breakout sessions, and evening functions, where you’ll get in on knowledge and conversations that can only happen in a live event atmosphere. Check out the Session Catalog now. All of our Breakout Sessions and Instructor-led Labs are focused on Microsoft Dynamics CRM 2015. Don’t miss your chance to meet the members of the R&D team and speak directly to the experts! Looking for more hands-on training? Check out the Deep Dive Workshops. Scheduled around the Microsoft Dynamics Technical Conference and offered at half the usual price (use code HaLF007), these intensive workshops help you maximize your learning and make the most of your trip to Seattle.
One of a few practices I see when people customize Dynamics CRM that usually comes back to haunt them during update rollups or upgrades is directly referencing the CSS files and classes that come with the product. It’s an innocent enough mistake, but the CSS files which ship with Dynamics CRM are intentionally not documented in the SDK. Directly referencing them is not supported. The Dynamics CRM team reserves the right to change them at any point, just like they reserve the right to change the structure of their html. That’s why direct HTML DOM manipulation of the UI the server creates isn’t supported either. Of course, you can manipulate the DOM of the web resources you author as much as you like. If you think about it, this makes perfect sense. I am not aware of any product out there that shield you from future changes if you hardcode your extensibility code to html/css structures. So what should you do? Well, you should create your own CSS files which mimic the CRM look and feel and reference those from your web resources. That way, when anything changes with the Dynamics CRM codebase, you are shielded from any ripple effect. You’re customizations may look out of place if major colors or fonts change. However, if you structure your CSS right (i.e. don’t copy paste, reuse), then you should be able to adjust to those changes with less impact. Ok, but how? Here’s a great article from the Dynamics CRM in the Field blog which walks you through the fundamentals:
“I have a touchscreen. I want to capture a signature in a Dynamics CRM form. If the signature hasn’t been saved, then I want to allow a user to provide their signature. The next time the record is loaded, after the signature has been saved, I want to load an imagine of the signature to prevent ‘resigning’.”
This is a relatively simple thing with Dynamics CRM thanks to web resources and Xrm.Page. The general concept is to embed an html web resource in the form that captures the signature using the html5 canvas (preferably using an existing control vs. low level canvas programming). Before saving, you want to copy the data from the canvas control into a Multiple Lines of Text type hidden field on the form so the data is stored when the record is saved. Finally, when the web resource is loaded, you want to check if the field has data in it. If so, you can assume a signature was previously recorded and just show the data as an image.
Here’s the entire source code for a basic implementation:
1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml"> 3<head> 4<title>Signature</title> 5<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js"></script> 6<script src="scripts/jSignature.min.js"></script><!-- download from http://willowsystems.github.io/jSignature/#/about/ --> 7</head> 8<body> 9<img id="sigImage" alt="This is an image of the persons signature." style="display:none"/>10<div id="sigPanel" style="display:none">11<div id="signature"></div>12<button id="clear">Clear</button>13</div>14<script type="text/javascript">15 $(function () {
16var sigImage = $("#sigImage");
17var sigPanel = $("#sigPanel");
18var sig = $("#signature");
1920var Xrm = window.parent.Xrm;
21var sigBase64Attribute = Xrm.Page.getAttribute("msftpoc_esigbase64"); //replace this with your hidden "multiple lines of text" field with a max length of 1,048,57622var sigBase64Value = sigBase64Attribute.getValue();
2324 sig.bind("change", function (e) {
25 sigBase64Attribute.setValue(sig.jSignature("getData"));
26 });
272829if (sigBase64Value !=null) {
30 sigImage.css("display", "inline");
31 sigImage.attr("src", sigBase64Value);
32 } else {
33 sigPanel.css("display", "inline");
34 sig.jSignature();
35 $("#clear").click(function() {
36 sig.jSignature("clear");
37 });
38 }
39 });
40</script>41</body>42</html>43
All you have to do is add this web resource to your form (make sure you read instructions in the comments) and update the code to reference your field name. A few things to note:
The hidden field on the form for my entity is called msftpoc_esigbase64 and uses the Multiple Lines of Text type of Dynamics CRM. Make sure to change the code to match your field name.
For simplicity, I chose to use the default data format of the jSignature control which is a base64 encoded string (hence my field name). Since base64 encoded strings can be big, I set the max length field to 1,048,576 which is the largest Dynamics CRM allows. The jSignature control supports other formats. You could clearly improve on performance of this sample by using one of the smaller string formats.
My code doesn’t handle save/autosave side effects. I simply copy the signature date to the hidden field using the change event of the jSignature control. A more robust implementation would perhaps wire up to Xrm.Page.data.entity.addOnSave() and intelligently determine whether to copy the data into the field based on save state. You might also want to consider switching to the image after as successful OnSave with signature if that makes the most sense for your requirements. I’ll leave that up to you as an exercise for improvement.
Here are a couple screenshots for a quick visualization.
Before Save (signature capable canvas with clear button):
With the release of CRM 2011 UR12, which introduced cross browser support, and the release of CRM 2013, there were two tools made available to you to check both your JavaScript code and your server side code for unsupported customizations:
There’s an excellent blog post about these tools with video walkthroughs here.
I’ve spoken with many customers/partners lately about these tools in the context of verifying where they stand for upgradability and creating a remediation plan for any unsupported customizations that might break after upgrading. One of the things I have also been emphasizing is how these tools can continued to be used in your development cycles to run a sanity check scan on new customizations. By introducing this approach into your testing process, you decrease the probability you are implementing unsupported customizations that can break during upgrades.