Saturday, 26 May 2012

Open Silverlight application on click of custom ribbon button in CRM 2011

In this post we will see how we can open a Silverlight application on click of a custom button in CRM 2011.

First of all create a Silverlight web application which you want to execute on button click in CRM application.

Compile your Silverlight Application. In the web project of your application you will find a ClientBin folder. When you compile your application a xap file is created under the ClientBin folder. Create a webresource of type xap and upload the xap file created under ClientBin folder.

Now second step is to embed the Silverlight application in an html file. Create an html file within your Silverlight application web project and add this code.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
 
<head>
    <title>ExpenseNote</title>
    <style type="text/css">
    html, body {
        height: 100%;
        overflow: auto;
    }
    body {
        padding: 0;
        margin: 0;
    }
    #silverlightControlHost {
        height: 100%;
        text-align:center;
    }
    </style>
    <script type="text/jscript" src="../../ClientGlobalContext.js.aspx"></script>
   1:  
   2:     <script type="text/javascript" src="../JavaScripts/Silverlight.js">
   1: </script>
   2:     <script type="text/javascript">
   3:       function onSilverlightError(sender, args) {
   4:         
   5:             var appSource = "";
   6:             if (sender != null && sender != 0) {
   7:               appSource = sender.getHost().Source;
   8:             }
   9:             
  10:             var errorType = args.ErrorType;
  11:             var iErrorCode = args.ErrorCode;
  12:  
  13:             if (errorType == "ImageError" || errorType == "MediaError") {
  14:               return;
  15:             }
  16:  
  17:             var errMsg = "Unhandled Error in Silverlight Application " +  appSource + "\n" ;
  18:  
  19:             errMsg += "Code: "+ iErrorCode + "    \n";
  20:             errMsg += "Category: " + errorType + "       \n";
  21:             errMsg += "Message: " + args.ErrorMessage + "     \n";
  22:  
  23:             if (errorType == "ParserError") {
  24:                 errMsg += "File: " + args.xamlFile + "     \n";
  25:                 errMsg += "Line: " + args.lineNumber + "     \n";
  26:                 errMsg += "Position: " + args.charPosition + "     \n";
  27:             }
  28:             else if (errorType == "RuntimeError") {           
  29:                 if (args.lineNumber != 0) {
  30:                     errMsg += "Line: " + args.lineNumber + "     \n";
  31:                     errMsg += "Position: " +  args.charPosition + "     \n";
  32:                 }
  33:                 errMsg += "MethodName: " + args.methodName + "     \n";
  34:             }
  35:  
  36:             throw new Error(errMsg);
  37:         }
  38:     
</script>
</head>
<body>
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost">
      <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
          <param name="source" value="../XAP/ExpenseNote.xap"/>
          <param name="onError" value="onSilverlightError" />
          <param name="background" value="white" />
          <param name="minRuntimeVersion" value="4.0.50826.0" />
          <param name="autoUpgrade" value="true" />
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
               <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
          </a>
        </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
    </form>
</body>
</html>

Note:

1) In the source parameter specify the path of your xap webresource correctly.
Here name of the webresource is ink_/XAP/ExpenseNote.xap and so the value for source is “../XAP/ExpenseNote.xap”, a relative path.

2) Also add the SilverLight.js file as a webresource. You can find the Silverlight.js file in sdk in the Silverlight example projects.

Now create a webresource and upload this html file. We have named this html webresource as CreateExpenseNote.html.

Now we need to open this html file on click of a button.

For this we will create a button. You can create button using the Visual Ribbon editor. To use Visual Ribbon Editor refer this link http://ankit.inkeysolutions.com/2012/01/crm-2011-how-to-use-visual-ribbon.html

In the Visual Ribbon Editor define the action for the button as given below:

clip_image002[4]

In Action you can either directly specify a URL which will be accessed on button click or you can specify a javascript function which is defined within a webresource of type javascript file. In this example we would be using a javascript function defined within a webresource.

Here OpenSilverLightControl is the function that contains code to open the CreateExpenseNote.html file and OpenExpenseNote.js is the webresource within which the function is defined.

function OpenSilverLightControl()
 {
var serverUrl = Xrm.Page.context.getServerUrl();          window.showModalDialog(serverUrl+'/WebResources/ink_/html/CreateExpenseNote.html', " ","dialogWidth:800px ; dialogHeight:600px; center:yes;resizable:yes");
}

So on button click the CreateExpenseNote.html file which embeds the Silverlight application, is displayed as a ModalDialog .

Friday, 4 May 2012

Dynamics CRM 2011 - Client side Context Reference

Today, I came across couple of very useful links on Client-Side Context Reference.

http://www.resultondemand.nl/support/sdk/d7d0b052-abca-4f81-9b86-0b9dc5e62a66.htm
http://technet.microsoft.com/en-us/library/gg328399.aspx

I would like to post the consolidated details of the same here in below post.

Your code will need to operate within a context where a number of variables are not known at design time. The context object provides methods which can be used to retrieve information that is specific to a user, an organization or parameters passed to a page.

Following are the methods of the context object:-

· getAuthenticationHeader
It is a deprecated method used to return the encoded SOAP header which is necessary to use Dynamics CRM 4.0 web service calls using Microsoft Jscript.

· getCurrentTheme
This method returns a string which represents the theme currently chosen by the user in Microsoft Office Outlook.

· getOrgLcid
This method returns the LCID value representing the base language for the organization.

· getOrgUniqueName
It returns the unique text value of the organizations name.

· getQueryStringParameters
This function returns the query string arguments as an array of key value pairs.

· getServerUrl
This method returns the base server URL. The URL format varies for on-premises Microsoft Dynamics CRM 2011, Microsoft Dynamics CRM Online or working offline with Microsoft Dynamics CRM for Microsoft Office Outlook with Offline Access.

· getUserId
It returns GUID value of the SystemUser.Id value for the current user.

· getUserLcid
This method returns the LCID value of the Language Pack that the user selected as their preferred language.

· getQueryStringParameters
This function returns the query string arguments as an array of key value pairs.

 · getUserRoles
This function returns an array of string that represent the GUID values of each of the security roles that the user is associated with. This method does not return GUID values that represent the team security roles that the user may belong to.

 · isOutlookClient
This function returns a Boolean value which indicates if the user is using the Microsoft Dynamics CRM for Microsoft Office Outlook client.

 · isOutlookOnline
This function returns a Boolean value indicating whether the user is connected to the Microsoft Dynamics CRM server while using the Microsoft Dynamics CRM for Microsoft Office Outlook with Offline Access client. When this function returns false, the user is working offline without a connection to the server. They are interacting with an instance of Microsoft Dynamics CRM running on their local computer.

 · prependOrgName
It prepends the organization name to the specified path.

Drag and Drop Listbox

Glad to announce that “Drag and Drop Listbox” for Dynamics CRM 2011 was successfully placed at Dynamics Marketplace.

Give it a whirl.
http://dynamics.pinpoint.microsoft.com/en-IN/applications/drag-and-drop-listbox-12884936087

Friday, 27 April 2012

Embedding custom font or Dynamics CRM font in Silverlight 4.0

When you need to use a custom font/Dynamics CRM font which is not available in your Silverlight applications then just “embed” it as shown in this blog.

First of all get the font file (.ttf), if font is already exists at your system then you could find it at “C:\Windows\Font”; otherwise download that font file from the internet.

Here I’ve created simple Silverlight application having a label with Verdana fontfamily, as shown below.

image

Now, I want to change FontFamily for Label1 from “Verdana” to “Segoe UI” which is not available in Silverlight fonfamily.

Follow the below steps.

· Right click on Project.

· Select Add -> Existing Item.

· Select “segoeui.ttf” file.

· Click on Add.

clip_image004

Now, you could see “segoe.ttf” file in solution explorer.

clip_image006

Replace, FontFamily="Verdana" with FontFamily="segoeui.ttf#Segoe UI" in above code, Where “segoeui.ttf” is font file name that we recently imported in our application, “Segoe UI” is the name of the font available in that file and “#” works as delimiter. That’s it we are done.

image

Friday, 20 April 2012

Programmatically change the customization for a system/custom entity in CRM 2011

Each and every entity of Dynamics CRM is having a “Formxml” that outlines the customization of the particular entity. In this blog I am going to explain you how to update the “Formxml” of any System/Custom entities.

To change customization we’ve to follow these steps.
· Retrieve formxml for that particular entity.
· Apply changes to that formxml.
· Publish updated formxml to CRM.

Here I’ve used custom entity “acm_airport” and applied changes on its formxml.
As shown in below screen shot there is a tab named as “Extra” having a section. I would like to add one more section with the same name (“Extra”) in this tab

image

Add following files in your class library project from this location “..\sdk\samplecode\cs\helpercode” once you have successfully downloaded Dynamics CRM SDK(5.0.7).
· crmservicehelpers.cs
· myorganizationcrmsdktypes.cs
· optionsets.cs

Use below code to get the fetchxml of acm_airport entity.
using System.Xml;
using System.Xml.XPath;
using Microsoft.Xrm.Sdk.Query;
 
string entityName = "acm_airport";
string tabName = "tab_Extra";
string sectionName = "section_Extra";
 
#region Retrieve Form XML
//Creates query expression to retrieve fromxml and form id for the specified object type code and form type='main'
QueryExpression myFormXml = new QueryExpression
{
EntityName = SystemForm.EntityLogicalName,
ColumnSet = new ColumnSet(new string[] { "formxml" }),
Criteria = new FilterExpression
{
Conditions = 
{
new ConditionExpression
{
//CRM represents EntityTypeName in ObjectTypeCode attribute
//Set 'Objecttypecode' as an Attribute name 
AttributeName = "objecttypecode",
Operator = ConditionOperator.Equal,
 
//set 'entityname' as value of an attribute
Values = { entityName }
},
new ConditionExpression
{
AttributeName = "type",
Operator = ConditionOperator.Equal,
Values = {"2"}
}
}
}
};
SystemForm systemForm = null;
EntityCollection entityCollection = organizationService.RetrieveMultiple(myFormXml);
 
#endregion
In continuation with above code, use below code to update the retrieved formxml with new section named as “Extra” and publish the customization changes.

if (entityCollection.Entities.Count > 0)
{
#region Validate Specified Tab,Section and Insert Control
systemForm = (SystemForm)entityCollection[0];
 
//Loads form xml to customization
XmlDocument customization = new XmlDocument();
customization.LoadXml(systemForm.FormXml);
 
//Creates XPathNavigator
XPathNavigator xNav = customization.CreateNavigator();
 
//Set path to insert new section on mainform.
string validateTab = "//tabs/tab[@name='" + tabName + "']";
string validateSection = validateTab + "/columns/column/sections" +
"/section[@name='" + sectionName + "']";
 
//Creates new row to place new web resource control with necessary parameters
string newDDList = "<section name='" + sectionName + "' showlabel='false' showbar='false'                 locklevel='0' id='{6851ca85-b2a6-9689-ead3-3813de16082e}'                         IsUserDefined='0' layout='varwidth' columns='11' labelwidth='115'                     celllabelalignment='Left' celllabelposition='Left'> "+
"   <labels> "+
"    <label description='Extra' languagecode='1033' />"+
"   </labels> "+
"   <rows> "+
"     <row> "+
"     </row> "+
"   </rows> "+
"</section>";
 
XPathNodeIterator xIterTab = xNav.Select(xNav.Compile(validateTab));
 
 
//Validate specified Tab exists or not 
if (xIterTab.Count == 0)
{
throw new InvalidPluginExecutionException("Invalid Tab Name, Please verify");
}
 
XPathNodeIterator xIterSection = xNav.Select(xNav.Compile(validateSection));
 
//Validate specified Section exist or not 
if (xIterSection.Count > 0)
throw new InvalidPluginExecutionException("The Section is already configured on a                                     form. You cannot specify the existing "
+ "Section Name");
 
if (xNav.CanEdit)
{
XPathExpression xExpression = xNav.Compile(validateTab +                                             "/columns/column/sections/section");
 
//Select node using specified path in expression.
XPathNodeIterator xIter = xNav.Select(xExpression);
if (xIter.Count > 0)
{
//Moves navigator to next node from current set node
while (xIter.MoveNext())
{
//Checks position of current node is last node or not.
if (xIter.CurrentPosition == xIter.Count)
 
//if currnt node is last node then insert new element    
xIter.Current.InsertAfter(newDDList);
}                            }
}
#endregion
 
#region Update Form xml
//Now we place the updated FormXml back into the systemform, and update                     it.
systemForm.FormXml = customization.InnerXml;
try
{
organizationService.Update(systemForm);
}
catch (Exception)
{
throw new InvalidPluginExecutionException("Failure: Updating the                     Formxml changes...");
}
#endregion
}
}

After implementing the above code in a plug-in you can verify the updated formxml either opening a record or Airport entity or by validating the same via form customization. You could see the new section with “Extra” in the tab “Extra” as shown below.

image

Similarly, you can apply other required customization changes programmatically.

I hope this will be useful.

Friday, 13 April 2012

Getting use of PublishXmlRequest SDK message to publish an Entity or a Web Resource

In Microsoft Dynamic CRM, when we perform any customization changes it is required to publish those changes. Below is the code which we can use to publish an Entity or a WebResource using “PublishXmlRequest” SDK message.

This code helps you to publish entity customization changes. Replace your entity’s logical name with below highlighted “entityName” variable.
#region Publish FormXMl
//Publish entity for which formxml has been changed 
PublishXmlRequest publishRequest = new PublishXmlRequest();
publishRequest.ParameterXml ="<importexportxml>" +
"    <entities>" +
"        <entity>" + entityName + "</entity>" +
"    </entities>" +
"    <nodes/>" +
"    <securityroles/>  " +
"    <settings/>" +
"    <workflows/>" +
"</importexportxml>";
try
{
organizationService.Execute(publishRequest);
}
catch (Exception)
{
throw new InvalidPluginExecutionException("Failure: FormXml                                                 publishing...");
}
#endregion

Similarly, we can publish a web resource using below code. Here you have to use a GUID of web resource record. Replace your web resource GUID with below highlighted value.

#region Publish Web Resource
 
PublishXmlRequest publishRequest = new PublishXmlRequest ();
 
publishRequest.ParameterXml =
"<importexportxml>" +
"   <webresources>"+
"       <webresource>{" + webResource.Id +"}</webresource>"+
"   </webresources>" +
"</importexportxml>";
try
{
organizationService.Execute(publishRequest);
}
catch (Exception)
{
throw new InvalidPluginExecutionException("Failure: WebResource publishing...");
}
#endregion

Below link will help you to identify what all other solution components can be published with PublishXmlRequest.

http://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.publishxmlrequest.parameterxml.aspx

Wednesday, 4 April 2012

Inkey solutions unveils another outstanding add-on for Dynamics CRM 2011 – GoalMetricEx

 

After getting a huge success for Drag and Drop Listbox, Inkey solutions unveils another outstanding add-on – GoalMetricEx.

This add-on enables you to calculate average of configured rollup fields on a Goal with Goal Metric of type Amount.

The calculated results will be displayed in a similar way on your existing Goal form.

Press the Recalculate button and GoalMetricEx will automatically generate the average values for a particular Goal.

For more details please refer below URL

http://www.inkeysolutions.com/DynamicsCRMAddOns.html