Enhancements to solution patches in 2016

Introduction

Now moving forward we will look at a common scenario of sending out Patches for your solution. Often it happens that you may need to update a few components of your managed solution and ideally would like to have a way to only have those shipped and then have a way to compile all of these patches in the next release of the solution. This helps with better versioning control and management of the solution assets.

Patches

Taking it forward from our previous article, here is what our solution looked like.

Keep your eye on the Version number of the solution as this is one of the critical thing which will come to notice as we move ahead.

Now suppose due to some requirement changes I have to increase the maximum length for “First Name” field of Contact from 155 to 175.

Since this field was a part of the earlier solution that we had and this is the only change we need to make to that solution, we will go ahead and create a patch for the original solution

Use the “Clone a Patch” button added to the solutions views

Notice the other buttons as well “Clone Solution” and “Apply Solution Upgrade”, this completes the entire solution management architechture.

It is a good practice to increment the version number for a proper version management of the solution. Since this is a patch it only allows you to modify the last 2 digits in the version.

This creates the following new solution.

Add only the Contact “First Name” field to the solution and update the length as shown below.

When you import this patch on the client environment this solution will be applied on top of the base solution and only the “firstname” field will be updated.

You can create multiple patches for a solution. To create another patch you would select the original solution and click “Clone a Patch”.

The original solution can no longer be modified.

In the Target system, you can delete the managed solution of a patch without affecting the base solution installed there.

The patches don’t have a dependency on each other, so in the target system I deleted the first patch that was imported and then imported the second patch and it works just fine. So that’s huge plus, since one of the problems with earlier solution management architecture was the dependencies that would be created between managed solutions. So here there is no dependency of the patches amongst them. But of course they do need the base solution present since they are patch for the base solution.

Uninstalling the base solution on the target also automatically uninstalls all the patches that were installed for the base solution.

When you want to plan your next version of the solution, you usually want to rollup all of the patches that were released for the base solution into the new solution, before you can add new changes in there. This can be done using the “Clone Solution” button.

Now this time, you are only allowed to change the major and minor parts of the version.

Once the operation completes, you will find the patches deleted and the base solution version updated.

This solution is now available for editing as well.

When the Upgrade solution is imported on the target system, it auto detects this to be an upgrade to an existing installed package and notifies you of the same.

On the next step of the import wizard, you get the option to choose if you want this imported as “Holding Solution”. This option will show up and checked by default if the target organization has base solution and patches for base solution installed. You can learn more about the “Holding Solution” concept here

When the solution import completes, you see a new option “Apply Solution Upgrade” since you chose to import this as a holding solution.

If you do not choose to apply the solution upgrade, you will see three solutions in the target system.

Now choose the original Base solution on the target system and click on the “Apply Solution Upgrade” button to keep a single solution for the package instead of the three that appear now

If there were no patches installed in the target system and the “Stage for Upgrade” option is unchecked, you have the option to check it if you want. If you leave it unchecked it simply updates the solution and you do not need to “Apply Solution Upgrade”.

Conclusion

Though I have only explored this using basic customizations to entities, the whole solution management framework from creating a solution to patching to moving it to the next release and similarly “upgrading solution” on the target system appears that, it would reduce if not end a lot of “solution import” woes of the ISV community.

Connecting to CRM using console application

Find the code to connect to your organization to perform some CRUD operations, please note this code is completely tested and can be used without any doubt

namespace console_to_connect
{

//namespaces to include
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk.Query;

namespace ConnectToCRM
{
class Program
{
static IOrganizationService _service;
static void Main(string[] args)
{
EntityCollection ec = null;
try
{
ConnectToMSCRM(“pavan@xrm.onmicrosoft.com”, “XRM”, “https://xrm.api.crm8.dynamics.com/XRMServices/2011/Organization.svc”);// connect to your organization
}

catch(Exception ex)
{

}
Guid userid = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).UserId;//Getting the current user who was running this operation
if (userid != Guid.Empty)
{
Console.WriteLine(“Connection Established Successfully”);
Console.ReadKey();
}

else return;
}
public static void ConnectToMSCRM(string UserName, string Password, string SoapOrgServiceUri)
{
try
{
ClientCredentials credentials = new ClientCredentials();
credentials.UserName.UserName = UserName;
credentials.UserName.Password = Password;
Uri serviceUri = new Uri(SoapOrgServiceUri);
OrganizationServiceProxy proxy = new OrganizationServiceProxy(serviceUri, null, credentials, null);
proxy.EnableProxyTypes();
_service = (IOrganizationService)proxy;

QueryExpression query = new QueryExpression
{
EntityName = “user”,
ColumnSet = new ColumnSet(UserName, Password)
};

}
catch (Exception ex)
{
Console.WriteLine(“Error while connecting to CRM ” + ex.Message);
Console.ReadKey();
}
}
}
}
}

FAQ’s on plugin development and registration

1. How do I find the right Message for registering my plug-in?

· An action in CRM can be performed using different SDK operations. So in order to find the correct subset of messages, you need to filter the messages by entity. Then you can register the plug-in on all the messages that look closer to the functionality.

· To make the search easier, I created an excel sheet with all valid list of Messages and Entities for plug-ins which is located at http://code.msdn.microsoft.com/crmplugin. Filter the list by the entity name to find the correct subset of messages.

2. Why do I need to register on SetState and SetStateDynamicEntity separately?

· As I mentioned earlier there are multiple messages that perform the same action in CRM. One such example is SetStateRequest and SetStateDyanmicEntityRequest . If you want to write a plug-in on SetState, then you need to register it on both messages.

3. Why does Opportunity State change not caught when I register on SetState alone?

· This is one more example of multiple SDK operations valid for an action in CRM. If you look at the Opportunity entity, you shall find that there are Lose, Win, Setstate, SetStateDynamicEntity requests that change the State of an opportunity. So you need to register your plug-in on all the mentioned messages.

4. Why did my plug-in not fire on Create Account, when Opportunity is converted to Account?

· In CRM 3.0 we had this problem. So, If you want your plug-in to be fired when an action happens as a result of another action, you need to register the plug-in in the Child pipeline. Plug-in Registration tool allows you to specify this option during the Step registration process.

· If you register the plug-in with InvocationSource=Parent, then it is fired only on the primary action

5. How do I pass configuration data to plug-in? I don’t see support for app.config

· Hard coding connections, customer configuration in plug-in is always a bad idea. So if you need some information, either you had to read from Registry or from a File. Multi Server deployment is major problem in either of these cases. So wouldn’t it be nice if CRM provided some functionality to store the configuration data to the plug-in just like it stores the assemblies in database? Well, you have it in the form of SdkMessageProcessingStep.configuration and SecureConfiguration properties. Both of these properties are strings. They can be set when registering the Step and their values are available in the plug-in constructor at runtime.

· SdkMessageProcessingStep is an OrgOwned entity, so any user in CRM can read the values from this entity via SDK. So data stored in it is not restricted to administrators only.

· On the other hand, SecureConfiguration can only be read by CRM Administrators. So if you want to store username, pass word information, etc., save it in this property.

· For a sample look at SamplePlugins.LogContextToCRM in the downloads section

6. How to read the IPluginExecutionContext.InputParameters Property bag and what is the structure?

· InputParamaters property is a serialized version of the SDK Request operation

· Microsoft CRM SDK has good explanation about this property http://msdn2.microsoft.com/en-us/library/cc151087.aspx

7. I need to get an Image of the entity when the update requested is fired

· Register a PreImage on the Step

· Context.PreImages[“entityalias”] should have the DynamicEntity

8. I would like to be notified when IncidentResolution entity is created. I also needed information about the related incident entity. How do I get this information?

· IncidentResolution entity is created as part of Resolve Incident request. So, you can only catch this event if you register on Child pipeline for Create of IncidentResolution entity. You can parse the incidentid from the InputParameters property bag

· However if you need to read custom attributes or other attributes on the incident, you have to call CRM. Since it is a child pipeline, we restrict you in calling CRM by not providing the Proxy. You can work this around by creating a proxy by yourself.

· PluginHelper. GetCrmProxyUsingEndpointUrlInChildPipeline in the downloads section has sample

9. How to get the EntityId in the Plug-in?

· I have created a PluginHelper.cs available in the download section, which helps you understand how to retrieve the entityId based on the message. You can extend it for other messages too. In short you need to look at the Request and see where the entityId is available and then retrieve it accordingly in the plug-in.

· Look at the RetrieveEntityId plug-in in the downloads section.

10. Can I look at what is in the IPluginExecutionContext without debugging?

· IPluginExecutionContext has lot of properties and most of them are dictionaries. I understand that it is hard for developers to know what its contents are before enumerating or debugging. So I created a plug-in that serializes the IPluginExecutionContext and writes it back to CRM so that you can view the Xml in the Form.

· SamplePlugins.LogContextToCRM Plug-in in the download section creates the serialized Xml into the new_pluginContext custom entity. Once you register the plug-in on any message, you shall get the Context in the custom entity

11. How do I know if my plug-in is running in Outlook Offline mode or on the Server?

· You can use IPluginExecutionContext.IsExecutingInOfflineMode property

· SamplePlugins.AmIExecutingOffline plug-in in the download section demos the scenario

12. How do I know if the Request originated in the Outlook Offline mode and replayed?

· You can use CallerOrigin property

· SamplePlugins.OfflinePlaybackConflictResolution plug-in in the download section demos the scenario. It rejects all the updates on the entity from the Outlook Offline client, if the Server had an updated version of the same entity.

· SamplePlugins.MyPluginCallerOrigin plug-in also demos the scenario

13. What is Depth and CorrelationId in the IPluginExecutionContext?

· Depth is an integer property that we automatically increment when Plug-in makes a call back to CRM using web service. When the Depth reaches certain max value, we treat it as potential infinite loop and reject the call.

· CorrelationId is a Guid that is set on the initial call to CRM and used later for tracking resultant calls.

· When you use CreateCrmService() method in the plug-in, we set these values on the proxy. However, if you create your own proxy, please copy these values so that the tracking is in place. PluginHelper.GetCrmProxyUsingEndpointUrlInChildPipeline in the download section has the sample code.

· We do recommend you to use our proxy so that we take care of all the minute details.

14. I registered my plug-in in Child pipeline and I can no longer create proxy to connect to CRM

· We disabled this feature since it is very easy to get into infinite loops as you are way low in the pipeline.

· But if you do have the scenario and absolutely need it, then you can create your own proxy. I have demonstrated this in the PluginHelper.GetCrmProxyUsingEndpointUrlInChildPipeline method but use with Caution !!!

15. What is the difference between InitiatingUserId and UserId in IPluginExecutionContext?

· You registred the plug-in to impersonate as UserA. If UserB makes a call to CRM which triggers the plug-in, then you get UserA in the UserId property and UserB in the IntiatingUserId property.

Column set query to retrieve data

The following code example shows how to use the ColumnSet class to specify what attributes to return from a query expression.

QueryExpression contactquery = new QueryExpression 
{
   EntityName="contact",
   ColumnSet = new ColumnSet("firstname", "lastname", "contactid") 
};

Xrm JS. API syntaxes

Hi All,

Here is file where you can find complete XRM utility javascript syntaxes, follow and download the image file below

Xrm Js syntaxes

Retrieve record using OData and JQuery in CRM 2011

Hi,

Below is the script to read a record using OData & JQuery

function retrieveRecord(id, odataSetName) {

// Get Server URL

var serverUrl = Xrm.Page.context.getServerUrl();

//The OData end-point

var ODATA_ENDPOINT = “/XRMServices/2011/OrganizationData.svc”;

//Asynchronous AJAX function to Retrieve a CRM record using OData

$.ajax({

type: “GET”,

contentType: “application/json; charset=utf-8”,

datatype: “json”,

url: serverUrl + ODATA_ENDPOINT + “/” + odataSetName + “(guid’” + id + “‘)”,

beforeSend: function (XMLHttpRequest) {

//Specifying this header ensures that the results will be returned as JSON.

XMLHttpRequest.setRequestHeader(“Accept”, “application/json”);

},

success: function (data, textStatus, XmlHttpRequest) {

readRecord(data, textStatus, XmlHttpRequest)

},

error: function (XmlHttpRequest, textStatus, errorThrown) {

alert(“Error – ” + errorThrown)

}

});

}

function readRecord(data, textStatus, XmlHttpRequest) {

alert(“Record read successfully!!”);

var account = data;

alert(“Name – ” + account.d.Name);

alert(“Id – ” + account.d.AccountId);

}

How do I call this method :-

  • Below is the sample function to read Account

var accountId = “”; // Assign account GUID

var odataSetName = “AccountSet”;

retrieveRecord(accountId,odataSetName );

New features in CRM 2016

CRM 2016 introduces a role-based experience for customer service agents. Users can view their current workload and interact with records through a real-time dashboard.

Cases can now be updated directly from the dashboard by selecting the case and the appropriate action.

Case Enhancements

Case management is simplified and better than ever. Users can now save case details directly on a case record and apply routing rules all in one action by clicking the Save & Route button.

Knowledge Management Capabilities

The new knowledge base article designer now features an enhanced WYSIWYG editor and allows for embedding videos and images. Articles can easily be scheduled to publish or expire for a future date. Knowledge can be enabled on any entity and over 80 languages are now supported. Articles can be shared with external users or analyzed internally to better understand how information is being used.

Word Templates

You can now standardize common CRM data-generated documents. Word templates can be initiated from any form or automated through a workflow. Extract data from CRM into a standardized word document with ease and create custom templates or leverage existing word templates from Microsoft!

Excel Templates

New Excel templates let you use a Microsoft Dynamics provided template or create your own reusable templates to quickly analyze data your way. CRM 2016 allows users to work with data from a downloaded template or from Excel Online. With the CRM Mobile Application, you can also export to Excel directly from a tablet or mobile device. Pretty Excel-lent, huh?

Delve

Unique to each user, Delve uses analytics to identify top trending documents in CRM relevant to the user. Delve looks for connections as to what the user is working on, common groups or teams, and identifies documents that may be relevant such as a newly saved presentation or proposal. Users can view trending documents relevant to them from a dashboard or Office 365.

*Note: data permissions still apply, meaning that if the user does not have permission to view the information it will not be presented.

Consolidated View of Documents in CRM

Display any Office document file from OneDrive for Business, SharePoint, or Office 365 groups directly in CRM. Documents will remain private until the user elects to share.

With the CRM Mobile App, these same documents can be viewed or modified directly from a tablet or mobile device.

CRM App for Outlook

Track emails, add Contacts from within an email, or create new records to track emails against all with the CRM App for Outlook. In addition to Internet Explorer and Chrome, CRM 2016 is expanded to include support for Firefox, Safari for Mac, and Outlook for Mac. One especially cool new feature is that you can track an email while composing it.

Updating CRM on the Go

In future blogs we will focus on Mobile enhancements and features specific to system administrators and customizers. However, we just had to leave you with this amazing new feature. Have you ever wanted to update a field from a mobile device leveraging touch capability? Let’s say you are an Account Manager and while having a conversation with a customer you want to update the Estimated Revenue field. By using a slider control, you can quickly update this field by simply moving the slider. Pretty awesome!

View usage activity metrics with a new preview feature, Organization Insights

With the latest release of Microsoft Dynamics CRM, we have delivered a new preview feature, Organization Insights, which provides the system administrator(s) of a CRM Online organization with the ability to view usage activity metrics to gain a better understanding of how well the CRM instance is being used.

The Organization Insights dashboard shows information such as top users and how many operations, page requests, etc., are occurring over various lookback periods.

org insi2

Specifically, the following metrics are provided as part of the Organization Insights preview feature:

  • Active Users – Total number of active users (unique users) who performed an operation that caused one of these SDK calls: Retrieve, RetrieveMultiple, Delete, Create, and Update.
  • Most Active Users (Reads) – Names of most active users who performed an operation that caused a Retrieve or Retrieve Multiple SDK call in the CRM instance over a selected time period.
  • Most Active Users (Changes) – Names of most active users who performed a Create, Update, or Delete SDK call in the CRM instance over a selected time period
  • Active Users Performing Specific Operations – Shows how many unique users are split across Create, Retrieve, RetrieveMultiple, Update, and Delete SDK calls.
  • Total Operations – Shows the total number of Create,Retrieve,Retrieve Multiple, Update, andDelete SDK calls for all entities in the CRM instance
  • Total Page Requests – Shows the number of requests for form,dashboards, andreports pages.

 

For more details about the Organization Insights preview feature, please refer to this TechNet article.

To enable Organization Insights
To enable the Organization Insights Preview feature, log into your CRM Online organization (running build 8.1.0.359or later), and then navigate to Settings->Administration->System Settings.

On the Previews tab, view the Supplemental Terms of Use for Microsoft Dynamics CRM Online Previews and select the check box to acknowledge your acceptance, and then to the right ofOrganization Insights Preview, select the Yes radio button.

When the feature is enabled, system administrators can access the associated dashboard from the System Dashboards dropdown list. System administrators will also be able to create their custom dashboards and add specific charts to their own CRM dashboards

Important points to note for the intellisense of calculated fields

Consider below scenario to understand calculated field intelligence logic.

1. I have created custom field called lookup and relate to system entity called ‘Unit’ with named ‘new_uomid’.

2.  Created new custom field as string (Calculated) and tried to set action (Calculated field) with lookup value as ‘new_uomid’.  I have added dot after ‘new_uomid’ field to get intellisense but it did not appears.

3. Then , I have created new custom field called lookup and relate to system entity called ‘Account’ with named ‘new_accountid’

4. Open existing string field and tried to set action (Calculated field) with lookup value ‘new_accountid’, then I have added dot to get intelligence and it is working properly.

Reason : Each entity have metadata property called ‘IsValidForAdvancedFind’. If this properly is true then only you will get intellisense option in calculated field for selected entity. In simple words if entity is visible in advanced filed view  then you will get intellisense option in calculated field.

Sample plugin to create record when other entity record was created

The below example shows how to create an Contact record whenever we had an account record getting created.

Find the code as below.

Step 1:


using System;
using Microsoft.Xrm.Sdk;// include this dll from SDK
namespace plugin_721
{
public class Class1 : IPlugin
{
public void Execute(IServiceProvider service1)
{
IPluginExecutionContext context = (IPluginExecutionContext)service1.GetService(typeof(IPluginExecutionContext));
if (context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
entity.LogicalName = "account";
try
{
Entity createcontact = new Entity("contact");
if (context.PrimaryEntityId != null)
{
createcontact["firstname"] = "pavan";
}
IOrganizationServiceFactory servicefactory = (IOrganizationServiceFactory)service1.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);
service.Create(createcontact);
}
catch (Exception ex)
{
//code you for displaying when exception was caught, not compulsory
}
}
}
}
}

view raw

Plugin.cs

hosted with ❤ by GitHub

Step 2: 

Dont forget to sign in the assembly.

Build the code in the visual studio to get the dll file.

Step 3:

Open Plugin registration tool from  crm 2016 SDK\SDK\Tools\PluginRegistration

  1. create a new connection
  2. give the organization login details select O365 if online
  3. Select your region
  4. Displays the organizations if found
  5. Click Register–>Register new Assembly–>Select your DLL
  6. Select sandbox & Database if online–> Register
  7. Goto the Assembly and create a new step for that
  8. Select the details asked, can select required pipeline execution order, stage, execution mode, deployment
  9. Enter register step
  10. Your plugin was registered
  11. Go and check, when you had created a new account, this code would create a contact pavan(You can give whatever you want).

Cheers,

PMDY