Usage of “SHARED VARIABLES” in Microsoft Dynamics CRM Plugins

Hi Friends,

Here come my new post regarding the usage of shared variables in Microsoft Dynamics CRM Plugins . This is not new topic in plugins , here are few thoughts about them because most of us ignore them while using in Plugins.

In order to explain this, i hope all of us know about ASP.Net session concept . Sessions are also used for storing data and using the same data in all the forms in entire application.Here session gets disposed once the application is closed.

In the same way , shared variables are used for storing the data in one plugin and use the stored data in different plugin . But the main limitations comes here is we need to register the plugin on same entity.

Limitations Of Shared Variables :

  • Data can be passed from plugin that is registered on Pre-Operation to plugin registered on Post Operation. Vice-versa is also not possible
  • Data can be passed between different plugins on the same entity

Creation of a shared variable Pre-Operation Plugin :

Context.SharedVariables[“Key”] = Value ;

or

Context.SharedVariables.Add(“Key”,Value);

Here context is IpluginExecutionContext in Plugins in Microsoft Dynamics CRM.

Usage of a shared variable in Post Operation  Plugin :

//its always better to check whether the key presents or not

if(Context.SharedVariable.ContainsKey(“Key”)

{

string value=Context.SharedVariable[“Key”].toString();

}

Here context is IpluginExecutionContext in Plugins in Microsoft Dynamics CRM.

Sample helper Code :

Pre-Create Account Plug-in

if (context.InputParameters.ContainsKey(“Target”) && context.InputParameters[“Target”] isEntity)
{
Entity target = context.InputParameters[“Target”] as Entity;
if (target != null)
{
// some wacky data validation
string city = target.GetAttributeValue<string>(“address1_city”) ?? string.Empty;
int numEmployees = target.GetAttributeValue<int>(“numberofemployees”);
int accountCategory = target.GetAttributeValue<int>(“accountcategorycode”);

// city is auckland, numEmployees > 100, account category is preferred customer
bool updateRelated = city.Equals(“Auckland”,StringComparison.InvariantCultureIgnoreCase) && numEmployees > 100 && accountCategory == 1;
context.SharedVariables.Add(“updatedRelated”, updateRelated);
}
}

Post-Create Account Plug-in

if (context.InputParameters.ContainsKey(“Target”) && context.InputParameters[“Target”] isEntity)
{
Entity target = context.InputParameters[“Target”] as Entity;
if (target != null)
{
if (context.SharedVariables.ContainsKey(“updatedRelated”))
{
bool updateRelated = (bool)context.SharedVariables[“updatedRelated”];
if (updateRelated)
{
// additional logic to update related records of the Account
}
}
}
}

This helps in building complex plugins without usage of hidden fields in Microsoft Dynamics CRM

Hope this helps 🙂

 

Set up ADX Studio Portal in Microsoft Dynamics CRM 2016

ADX Studio Portal is rich web portal which was acquired by Microsoft. These portals are rich in web content and can be integrated directly with Microsoft Dynamics CRM .

Walk through the below steps to integrate ADX Studio Portal with Microsoft Dynamics Version:

STEP 1:

Download ADX portal from the site “Click Here” by checking the compatible version for desired CRM version. Latest release of ADX Portal that is compatible for CRM is 7.0.0023 and it is released on 29th November 2016

STEP 2:

  • Run the Adxstudio Portals msi executable file and follow the instructions in the setup wizard
  • You can the check the ADX Portals installed files in the following path in your system  C:\Program Files (x86)\Adxstudio\XrmPortals.

STEP 3: Import  Adxstudio Portals Installer solution package into an existing CRM Organization

  • Login to Microsoft Dynamics CRM using a System User account with the System Administrator or System Customizer Security Role
  • Navigate to Settings
  • Click Solutions
  • Click Import

capture

  • Click Browse
  • captureBrowse to the Customizations folder in the Adxstudio Portals installation directory. Default location is C:\Program Files (x86)\ADXSTUDIO\XrmPortals\[version]\Customizations
  • Select AdxstudioInstaller.zip.
  • Click Open

capture

  • Click Next

capture

  • Click Import

capture

  • Wait for import to complete
  • Click Close

capture

  • Refresh your browser and the Adxstudio Installer

capture

For More References Please Visit to ADX portal Site ADX STUDIO PORTAL

Hope this helps some of our folks 🙂

 

Filter Sub Grid in MS CRM 2016 using JavaScript

Hi All,

It took quite long to write this post. I came across this scenario recently ,with one of my client requirement as “retrieve all the completed call reports(custom entity) whenever there is a change in master account and the relationship between completed call reports and accounts is N:1 

First i have retrieved the master account lookup id and name :

var parentAccount = Xrm.Page.getAttribute(“parentaccountid”);
if (parentAccount != null)
{

var parentAccountValue = parentAccount.getValue();
}
if (parentAccountValue != null)
{
var parentAccountId = parentAccountValue[0].id;
var parentAccountName = parentAccountValue[0].name;
}
else
{
return;
}

Then i have retrieved the Sub Grid control:

var relatedCallReports = window.parent.document.getElementById(“CompletedCallReports”);

Inorder to update the Fetch XML of Sub Grid i have constructed Fetch XML as follows:

var fetchXml = “<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’false’>”;
fetchXml += “<entity name=’po_completedcallreport’>”;
fetchXml += “<attribute name=’po_completed_accountsoldto’/>”;
fetchXml += “<attribute name=’po_company’/>”;
fetchXml += “<attribute name=’subject’/>”;
fetchXml += “<attribute name=’po_materialgroups’/>”;
fetchXml += “<attribute name=’po_reasonforcallvalues’/>”;
fetchXml += “<attribute name=’po_dateofcall’/>”;
fetchXml += “<attribute name=’ownerid’/>”;
fetchXml += “<attribute name=’statuscode’/>”;
fetchXml += “<attribute name=’po_completed_summary’/>”;

fetchXml += “<order descending=’false’ attribute=’po_dateofcall’/>”;
fetchXml += “<filter type=’and’>”;
fetchXml += “<condition attribute=’po_completed_accountsoldto’ operator=’eq’ uiname='” + parentAccountName + “‘ uitype=’account’ value='” + parentAccountId + “‘ />”;
fetchXml += “</filter>”;
fetchXml += “</entity>”;
fetchXml += “</fetch>”;

Then i used  SetParameter() function to update the Sub grid:

relatedCallReports.control.SetParameter(“fetchXml”, fetchXml);

Then i tested it on OnLoad of a Form but it generated an error on Sub Grid Control  as

relatedCallReports.Control=”Undefined”

This error is because CRM Sub Grids loads after CRM Form Loads and the function on Load executes first and Sub Grid control will be null.

So i used below Timeout function code to resolve this

setTimeout(‘updateSubGrid()’, 500);

Total Code :

function updateSubGrid()
{

var relatedCallReports = window.parent.document.getElementById(“CompletedCallReports”);
var parentAccount = Xrm.Page.getAttribute(“parentaccountid”);
if (parentAccount != null)
{

var parentAccountValue = parentAccount.getValue();
}
if (parentAccountValue != null)
{
var parentAccountId = parentAccountValue[0].id;
var parentAccountName = parentAccountValue[0].name;
}
else
{
return;
}

if (relatedCallReports == null)
{
setTimeout(updateSubGrid, 2000);
return;
}
else
{
var fetchXml = “<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’false’>”;
fetchXml += “<entity name=’new_completedcallreport’>”;
fetchXml += “<attribute name=’new_completed_accountsoldto’/>”;
fetchXml += “<attribute name=’new_company’/>”;
fetchXml += “<attribute name=’subject’/>”;
fetchXml += “<attribute name=’new_materialgroups’/>”;
fetchXml += “<attribute name=’new_reasonforcallvalues’/>”;
fetchXml += “<attribute name=’new_dateofcall’/>”;
fetchXml += “<attribute name=’ownerid’/>”;
fetchXml += “<attribute name=’statuscode’/>”;
fetchXml += “<attribute name=’new_completed_summary’/>”;

fetchXml += “<order descending=’false’ attribute=’new_dateofcall’/>”;
fetchXml += “<filter type=’and’>”;
fetchXml += “<condition attribute=’new_completed_accountsoldto’ operator=’eq’ uiname='” + parentAccountName + “‘ uitype=’account’ value='” + parentAccountId + “‘ />”;
fetchXml += “</filter>”;
fetchXml += “</entity>”;
fetchXml += “</fetch>”;
if (relatedCallReports.control != null) {
//Here i set the fetchxml directly to subgrid
relatedCallReports.control.SetParameter(“fetchXml”, fetchXml); //set the fetch xml to the sub grid
relatedCallReports.control.Refresh(); //refresh the sub grid using the new fetch xml
}
else {
setTimeout(‘updateSubGrid()’, 500);
}

}

}

Here make sure to set grid properties as below :

subgrid

Hope this helps 🙂

Get all the exception details in CRM and C#

Hi All,

This may be an old post , but felt may be useful to someone in getting all the exception details in CRM while extending the CRM functionality  using custom code.

There can be different types of Excpetions(Soap etc). This function helps in Retrieving all the exception details.

private static string GetExceptionDetails(Exception ex)

{

try

{

StackTrace stacktrace = new StackTrace(ex, true);

MethodBase methodbase = stacktrace.GetFrame(stacktrace.FrameCount – 1).GetMethod();

string errMsg = “”;

errMsg = “\n—————————- Start ———————————–\n” + Environment.NewLine;

errMsg += DateTime.Now.ToShortDateString().ToString() + ” “ + DateTime.Now.ToLongTimeString().ToString() + Environment.NewLine;

errMsg += “\n—————————————————————\n” + Environment.NewLine;

errMsg += “MESSAGE : “ + ex.Message + Environment.NewLine;

if (ex.GetType().Name == “SoapException”)// Exception Type

errMsg += “MESSAGE : “ + ((SoapException)ex).Detail.InnerText + Environment.NewLine;

else

errMsg += “MESSAGE : “ + ex.Message + Environment.NewLine;

errMsg += “INNER EXCEPTION : “ + ex.InnerException + Environment.NewLine;

errMsg += “EXCEPTION SOURCE : “ + ex.Source + Environment.NewLine;

errMsg += “OBJECT : “ + stacktrace.GetFrame(stacktrace.FrameCount – 1).GetFileName() + Environment.NewLine;

errMsg += “METHOD : “ + methodbase.Name + Environment.NewLine;

errMsg += “LINE NUMBER : “ + Convert.ToString(stacktrace.GetFrame(stacktrace.FrameCount – 1).GetFileLineNumber()) + Environment.NewLine;

errMsg += “EXCEPTION IN : “ + ex.TargetSite + Environment.NewLine;

errMsg += “STACK TRACE : “ + ex.StackTrace + Environment.NewLine;

errMsg += “\n—————————- End ———————————–\n” + Environment.NewLine;

return errMsg;

}

catch (Exception e)

{

return “Error Occured while generating the Error Details.” + e.Message;

}

}

 

Even we can find the exception details by using watch in visual studio while debugging.

Hope this helps 🙂

 

Impersonation in Custom Workflows in Microsoft Dynamics CRM 2016

“Impersonation” , this word plays a vital role in MSCRM to run our custom code on another user context . We can use impersonation in Custom workflows and run our workflows on different user context.

For example consider a user who has all admin privileges in CRM system and a on demand workflow need to be executed on another context . In the custom code, while creating organization service, use it as

IOrganizationService service=servicefactory.createOrganizationService(new Guid(“AdminUserId”));

Hope this helps in running workflows on another user context 🙂

For complete explanation , see Inogic blog,it is explained with a sample scenario

Export More than 10000 records to excel in Microsoft Dynamics CRM

This is post is in reference with  the blog written by “Peter Majer” . Hope this may help few of our folks 🙂

With Dynamics, the default maximum record count to export to Excel is 10,000.  While this may work for a lot smaller business without a lot of data, it won’t work for most organizations.  An instance of this came up recently where a client of ours kept hitting the 10,000 record limit though they had many more records to export.

Typically in the past, if the customer was CRM OnPremise, you would be able to access this setting (along with the other OrgDBOrgSettings) using direct SQL.  Updating these values with SQL definitely wasn’t supported, but at least you could have conversations of updating the settings if you had individuals that knew what they were doing, or you created a support ticket with Microsoft to help you out.

However, if you had CRM Online, these settings weren’t available to you through the UI or even through SQL since with Online, you don’t have direct SQL access to your database.  What can you do?

That’s where the OrgDBOrgSettings editor comes in to play.  You can download the managed solution from this link.  The process to get it installed and use it is pretty simple.  Download the managed solution from that link, import it in as a normal solution into your environment, and then open up the solution.

From the configuration page of the solution, you’ll see the different settings that you have access to, what the default value is, what the current value is, and what the maximum value is (there are some limitations – you cannot update the MaxRecordsForExportToExcel to 500,000,000).

6a00d8341e71de53ef01bb092332af970d-pi (1024×632)

To edit a value, either double click on a row, or click the Edit link in the row for that setting.  When you do so, you have the option to set a custom value, or revert back to the default.  A checkbox at the bottom of the configuration page can be set or unset which will display a prompt to confirm the change upon making an update.

image

image

If you try to set a value over the maximum, you’ll get a message stating the requested change wasn’t saved, and the value will remain as it currently is.

image

This is a great utility to make supported updates to the OrgDBOrgSettings without having to reach out to Microsoft Support.  For a full list of all the settings that can be updated and a description of what the setting drives, navigate to this link.  Also, for more explanation on how to use the tool and what it can be used for, see this post from Sean McNellis who created the solution.  While this solution has been available for some time now, we’re hoping this is a great refresher to let you know what tools are available for free to help you make changes on your own.

Hope this helps 🙂 cheers 🙂

 

Export a Generic list to excel in C#

Hi all this may be old post and most of them use it,felt to share so that it may be useful to some of our folks.

Problem: Export data from class(generic list) to excel.

Code:

public void ExportToExcel(List<Student> students)

{

// Load Excel application

Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();

 

// Create empty workbook

excel.Workbooks.Add();

 

// Create Worksheet from active sheet

Microsoft.Office.Interop.Excel._Worksheet workSheet = excel.ActiveSheet;

 

// I created Application and Worksheet objects before try/catch,

// so that i can close them in finnaly block.

// It’s IMPORTANT to release these COM objects!!

try

{

// ————————————————

// Creation of header cells

// ————————————————

workSheet.Cells[1, “A”] = “Name”;

workSheet.Cells[1, “B”] = “Class”;

workSheet.Cells[1, “C”] = “Section”;

 

// ————————————————

// Populate sheet with some real data from ” Studentts” list

// ————————————————

int row = 2; // start row (in row 1 are header cells)

foreach (Student student in students)

{

workSheet.Cells[row, “A”] = student .Name;

workSheet.Cells[row, “B”] = student .Class;

workSheet.Cells[row, “C”] =  student .Section;

 

row++;

}

 

// Apply some predefined styles for data to look nicely 🙂

workSheet.Range[“A1″].AutoFormat(Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic1);

 

// Define filename

string fileName = string.Format(@”{0}\ExcelData.xlsx”, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));

 

// Save this data as a file

workSheet.SaveAs(fileName);

 

// Display SUCCESS message

MessageBox.Show(string.Format(“The file ‘{0}’ is saved successfully!”, fileName));

}

catch (Exception exception)

{

 

}

finally

{

// Quit Excel application

excel.Quit();

 

// Release COM objects (very important!)

if (excel != null)

System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);

 

if (workSheet != null)

System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet);

 

// Empty variables

excel = null;

workSheet = null;

 

// Force garbage collector cleaning

GC.Collect();

}

}

Hope this helps 🙂