Tuesday 27 November 2012

Multiple entities selection in single look up:


If you create custom lookup in CRM, this lookup is oriented only for one entity.
I want to add possibility to select from some entities in one lookup.

I have custom lookup "originatingleadid". This lookup is oriented on Lead entity. I want to select from views of three different entities: Lead, Contact, User.

For this I've done some customization in opportunity entity, I've created three hidden text fields:
new_type - to save lookup type
new_guid - to save lookup guid
new_name - to save lookup name.
That is all customization.

I've developed three javascript function:

1. function to handle OnChange event on lookup.


function onchange()
{
var originatingLeadValue = Xrm.Page.getAttribute("originatingleadid").getValue();
if (IsNull(originatingLeadValue) || originatingLeadValue[0].type == "4")
{
// Lookup is null or there is a Lead, need to clear hidden fields. To clear one of them will be enough, we will be check this field during onload.
Xrm.Page.getAttribute("new_guid").setValue(null);
}
else
{
// Lookup contains Contact or User, so need to store lookup properties to our hidden fields.
Xrm.Page.getAttribute("new_type").setValue(originatingLeadValue[0].type);
Xrm.Page.getAttribute("new_guid").setValue(originatingLeadValue[0].id);
Xrm.Page.getAttribute("new_name").setValue(originatingLeadValue[0].name);
}
}

2. function to handle OnSave event on Opportuniry Form.

function onsave()
{
var originatingLeadValue = Xrm.Page.getAttribute("originatingleadid").getValue();
if (!IsNull(originatingLeadValue) && originatingLeadValue[0].type != '4')
{
Xrm.Page.getAttribute("originatingleadid").setValue(null);
}
}
 3. function to handle OnLoad event on Opportunity Form.

function onload()
{
lookuptypeIcons = '/_imgs/ico_16_2.gif:/_imgs/ico_16_4.gif:/_imgs/ico_16_8.gif';
lookuptypenames = 'contact:2:Contact,lead:4:Lead,systemuser:8:User';
lookuptypes = '2,4,8';
var savedId = Xrm.Page.getAttribute("new_guid").getValue();
var savedType = Xrm.Page.getAttribute("new_type").getValue();
var savedName = Xrm.Page.getAttribute("new_name").getValue();
var savedEntityName = savedType == "8" ? "systemuser" : "contact";
document.getElementById("originatingleadid").setAttribute("lookuptypes", lookuptypes);
document.getElementById("originatingleadid").setAttribute("lookuptypenames", lookuptypenames);
document.getElementById("originatingleadid").setAttribute("lookuptypeIcons", lookuptypeIcons);
document.getElementById("originatingleadid").setAttribute("defaulttype", "4"); // default type - Lead entity
var originatingLeadValue = Xrm.Page.getAttribute("originatingleadid").getValue();
if (IsNull(originatingLeadValue) && !IsNull(savedId))
{
var value = new Array();
value[0] = new Object();
value[0].displayClass = "ms-crm-Lookup-Item";
value[0].keyValues = new Object();
value[0].values = new Object();
value[0].onclick = "openlui()";
value[0].id = savedId;
value[0].entityType = savedEntityName;
value[0].typename = savedEntityName;
value[0].name = savedName;
value[0].type = savedType;
Xrm.Page.getAttribute("originatingleadid").setValue(value);
}
}
So, now you can select from  three different entity in one lookup :-)
Custom Lookup view

Friday 26 October 2012

Code for creation of new view:

 
System.String layoutXml =
@"<grid name='resultset' object='3' jump='name' select='1' 
    preview='1' icon='1'>
    <row name='result' id='opportunityid'>
    <cell name='name' width='150' /> 
    <cell name='customerid' width='150' /> 
    <cell name='estimatedclosedate' width='150' /> 
    <cell name='estimatedvalue' width='150' /> 
    <cell name='closeprobability' width='150' /> 
    <cell name='opportunityratingcode' width='150' /> 
    <cell name='opportunitycustomeridcontactcontactid.emailaddress1' 
        width='150' disableSorting='1' /> 
    </row>
</grid>";

                    System.String fetchXml =
                    @"<fetch version='1.0' output-format='xml-platform' 
    mapping='logical' distinct='false'>
    <entity name='opportunity'>
    <order attribute='estimatedvalue' descending='false' /> 
    <filter type='and'>
        <condition attribute='statecode' operator='eq' 
        value='0' /> 
    </filter>
    <attribute name='name' /> 
    <attribute name='estimatedvalue' /> 
    <attribute name='estimatedclosedate' /> 
    <attribute name='customerid' /> 
    <attribute name='opportunityratingcode' /> 
    <attribute name='closeprobability' /> 
    <link-entity alias='opportunitycustomeridcontactcontactid' 
        name='contact' from='contactid' to='customerid' 
        link-type='outer' visible='false'>
        <attribute name='emailaddress1' /> 
    </link-entity>
    <attribute name='opportunityid' /> 
    </entity>
</fetch>";

                    SavedQuery sq = new SavedQuery
                    {
                        Name = "A New Custom Public View",
                        Description = "A Saved Query created in code",
                        ReturnedTypeCode = "opportunity",
                        FetchXml = fetchXml,
                        LayoutXml = layoutXml,
                        QueryType = 0
                    };
                    
                    _customViewId = _serviceProxy.Create(sq);
                    Console.WriteLine("A new view with the name {0} was created.", sq.Name);
 

Friday 12 October 2012




Hiding navigation pane in mscrm2011:


Javascript approach:


//Ensure navitem is "quoted" to represent string
// bool: true = Visible, false = removed
var objNavItem = Xrm.Page.ui.navigation.items.get(navitem);
objNavItem.setVisible(bool);

C# code approach:


/// Retrieve the sitemap

QueryExpression query = new QueryExpression();
query.EntityName = "sitemap";
query.ColumnSet = new Microsoft.Xrm.Sdk.Query.ColumnSet(true);

EntityCollection col = _service.RetrieveMultiple(query);

Entity sitemap = null;
if (col != null && col.Entities.Count > 0)
   sitemap  = col.Entities[0];
 ///Parse the sitemap entity to an XDocument object
 string sitemapcontent = sitemap["sitemapxml"].ToString();
XDocument sitemapxml = XDocument.Parse(sitemapcontent);


You can now change the sitemap by modifying the sitemapxml object. After you made your changes, it's time to save these changes.

//// Update the sitemap
sitemap["sitemapxml"] = sitemapxml.ToString();
_service.Update(sitemap);


//// Publish the sitemap

PublishXmlRequest request = new PublishXmlRequest();
request.ParameterXml = "<importexportxml><sitemaps><sitemap></sitemap></sitemaps></importexportxml>";
_service.Execute(request);

Tuesday 9 October 2012

converting Managed solution to Unmanaged solution Work around:

This is useful when we have only Managed solution to work with but needs some more customization. Extract the Solution Zip file, Open solution.xml file in notepad application. Search for Managed Tag (E.g.: <Managed>1</Managed>), Now change the value from 1 to 0 and zip the files again and import it. That’s it The Solution is changed to Unmanaged. This can be imported and customized as per the need.

Monday 1 October 2012


 

CRM 2011 LINQ Operator Limitations:


.       from

       Supports one from clause per query.

          join

       Represents an inner join. You cannot perform outer joins.

          where

      The left side of the clause must be an attribute name and the right side of the clause must be a value.

      Supported String functions: Contains, StartsWith, EndsWith, and Equals.

          groupBy

      Not supported. FetchXML supports grouping options that are not available with the LINQ query provider.

      For more information, see Use FetchXML Aggregation.

          orderBy

       Supports ordering by entity attributes, such as Contact.FullName.

          select

       Supports anonymous types, constructors, and initializers.

          last

       The last operator is not supported.

          skip and take

       Supports skip and take using server-side paging. The skip value must be greater than or equal to the take value.

          aggregate

       Not supported. FetchXML supports aggregation options that are not available with the LINQ query provider. For more information, see Use FetchXML Aggregation.

 

FetchXML syntax:


Legend:

          Xxxx :=   à production

          (   ) à choice

          | à or

          ? à optional

          * à repeat

// à comments

 

FetchXml :=

  <fetch

    (page='page-number')? // start page default is 0

    (count='items-per-page')? // count default is 5000

    (utc-offset='utc-offset')? // utc-offset default is 0

    (mapping='logical')?

    (distinct = ('true' | 'false' | '1' | '0') )? //default false

    (paging-cookie='page-cookie')?

   >

    <entity name='entity-name'>

    Entity-Xml

    </entity>

  </fetch>

 

 Example:

<fetch page=‘10’ count=‘50’ distinct=‘true’

     page-cookie=‘Page1’>

    <entity name=‘account’ >

    …. Put Entity-Xml here ….

    </entity>

</fetch>

 

 

 

          Entity-Xml :=

          (<all-attributes/> | <no-attrs/> |Attribute-Xml* )

            ( Filter-Xml |  LinkEntity-Xml |  Order-Xml )*

          Attribute-Xml :=

            <attribute name='attr-name'

              (aggregate=(AggOp) alias='alias-name')?

            />

          AggOp :=

          (avg | min | max | count(*) |count(attribute name))

          Filter-Xml :=

            <filter (type= ('or' | 'and'))? // default is 'and'  >

            ( Condition-Xml | Filter-Xml )*

            </filter>

           

          LinkEntity-Xml :=

            <link-entity name = 'entity-name'

              // to is the column on the remote entity

              (to = 'column-name')? 

              // from is the column on the local entity

              (from = 'column-name')? 

              (alias = 'table-alias')?

              (link-type = ('natural' | 'inner' | 'outer'))?

            >

            Entity-Xml

            </link-entity>

          Order-Xml :=

            <order attribute='attr-name'

              (descending= ('true' | 'false' | '1' | '0')?

            />

 

 

Friday 28 September 2012

Some of the CRM Blogs:


Ronald Lemmen - http://ronaldlemmen.blogspot.com/
Philip Richardson - http://blog.philiprichardson.org/
Gonzalo Ruiz - http://gonzaloruizcrm.blogspot.com/
Ross Lotharius - http://www.avanadeblog.com/xrm/
CRM Team Blog - http://blogs.msdn.com/crm/default.aspx
Andy Bybee - http://bybeeworld.spaces.live.com/
Ben Riga - http://blogs.msdn.com/benriga/default.aspx
Ben Vollmer - http://blogs.msdn.com/midatlanticcrm/default.aspx
Menno te Koppele - http://blogs.msdn.com/mscrmfreak/
Simon Hutson - http://blogs.msdn.com/ukcrm/default.aspx
Aaron Elder - http://www.avanadeblog.com/xrm/
Frank Lee - http://microsoft-crm.spaces.live.com/
Guy Riddle - http://guyriddle.spaces.live.com/
Matt Witteman - http://icu-mscrm.blogspot.com/
Michael Höhne - http://www.stunnware.com
Mitch Milam - http://blogs.infinite-x.net/
Scott Colson - http://msmvps.com/blogs/crm/default.aspx

 

A good link , which explains clearly silver light webresource developmet in mscrm 2011 using rest end point:

 
 

Code snippet for custom wcf service calling from mscrm 2011 form java script:




Call the Custom WCF request in Java Script:

Var xmlhttp = new XMLHttpRequest ();

Retrieve the WCF URL from from “ApplicationConfig” Entity using following method.

Var WcfServiceUrlValue= GetConfigValueByKey (Key Name);

WcfServiceUrlValue=WcfServiceUrlValue.avd_ConfigValue;

xmlhttp.open('POST', WcfServiceUrlValue , false);

//Get the request XML from WCF Test Client or Using Feddler Tool

//Place the Inteface name and Method Name following highlighted text.

xmlhttp.setRequestHeader('SOAPAction', 'http://tempuri.org/IDynamicsPaymentService/UpdateExpiredCheque ');

xmlhttp.setRequestHeader('Content-Type', 'text/xml');

var data = '';

data+='<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">';

data+='<s:Body>';

   data+='UpdateExpiredCheque  xmlns="http://tempuri.org/">';

   data+='<data xmlns:d4p1="http://schemas.datacontract.org/2004/07/ UU.Crm.WCFService.DataContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">';

       data+='<d4p1:CaseNumber>12345</d4p1:CaseNumber>';

        data+='<d4p1:ChequeAmount>200</d4p1:ChequeAmount>';

        data+='<d4p1:ChequeNumber>23421213</d4p1:ChequeNumber>';

        data+='<d4p1:OriginalPaymentDate>1/10/2012</d4p1:OriginalPaymentDate>';

        data+='<d4p1:OriginalPaymentReference>1234</d4p1:OriginalPaymentReference>';

      data+='</data>';

    data+='</UpdateExpiredCheque>';

  data+='</s:Body>';

  data += '</s:Envelope>';

            xmlhttp.send(data);

            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");

            xmlDoc.async = false;

            xmlDoc.loadXML(xmlhttp.responseXML.xml);

//Check the Response Object  and Retrieve the tag values following way.

if (xmlDoc.xml != "") {

                var Msg;

                var ResponseCollection = xmlDoc.getElementsByTagName("a:ResponseCollection");

                if (ResponseCollection.length > 0) {

                    if (ResponseCollection[0].firstChild != null) {

                        Msg = "Message Severity :" + ResponseCollection[0].firstChild.childNodes[0].nodeTypedValue + '\n';

                        Msg += "Warning :" + ResponseCollection[0].firstChild.childNodes[1].nodeTypedValue;

                        alert(Msg);

                    }

                }

            }

Friday 21 September 2012

Sample code to modify the users  last viewed form id :


CRM saves the Id of the last form that a user viewed using the UserEntityUISettings entity, and any UserEntityUISettings record can be easily updated to set the Last Viewed form for a specific user:

//retrieve the user UI settings for a specific user and a specified entity:
QueryExpression query = new QueryExpression(UserEntityUISettings.EntityLogicalName);
query.Criteria.AddCondition("ownerid", ConditionOperator.Equal, userId);
query.Criteria.AddCondition("objecttypecode", ConditionOperator.Equal, entityObjectTypeCode);
EntityCollection UISettingsCollection = service.RetrieveMultiple(query);
if (UISettingsCollection.Entities.Count > 0)
{
//update the last viewed formId:
UserEntityUISettings settings = (UserEntityUISettings)UISettingsCollection[0];
settings.LastViewedFormXml = "<MRUForm><Form Type=\"Main\" Id=\"f5cfab6a-d4c2-4519-b68f-6e7485432e29\" /></MRUForm>";
service.Update(settings);
}

ODATA  restrictions in mscrm 2011:

 

Operator

Restrictions

$expand
· Max expansion 6
$top
· Page size is fixed to max 50 records
· $top gives the total records returned across multiple pages
$skip
· When using with distinct queries, we are limited to the total (skip + top) record size = 5000.
· In CRM the distinct queries does not use paging cookie are and so we are limited by the CRM platform limitation to the 5000 record.
$select
· One level of navigation property selection is allowed I.e.
…/AccountSet?$select=Name,PrimaryContactId,account_primary_contact
…/AccountSet?$select=Name,PrimaryContactId,account_primary_
contact/LastName&$expand=account_primary_contact
$filter
· Conditions on only one group of attributes are allowed. By a group of attribute I am referring to a set of conditions joined by And/Or clause.
· The attribute group may be on the root entity
.../TaskSet?$expand=Contact_Tasks&$filter=Subject eq 'test' and Subject ne null
· (or) on the expanded entity.
.../TaskSet?$expand=Contact_Tasks&$filter=Contact_Tasks/FirstName eq '123‘
· Arithmetic, datetime and math operators are not supported
· Under string function we support Substringof, endswith, startswith
$orderby
· Order are only allowed on the root entity.
Navigation
· Only one level of navigation is allowed in any direction of a relationship. The relationship could be 1:N, N:1, N:N
Accessing context data  in silvrlight webresource like cr for javascript:



If your Silverlight web resource is designed to be viewed in an entity form, the form has an Xrm.Page.context object you can use to access contextual information.
If you need your Silverlight application to appear outside the context of the form you must configure an HTML web resource to provide this context information by adding a reference to the ClientGlobalContext.js.aspx page. After this reference is added, your Silverlight application can access contextual information in the same way it can in an entity form. The following sample shows how to call the getServerUrl function from the Xrm.Page.context object.

private string serverUrl = "";
ScriptObject xrm = (ScriptObject)HtmlPage.Window.GetProperty("Xrm");
ScriptObject page = (ScriptObject)xrm.GetProperty("Page");
ScriptObject pageContext = (ScriptObject)page.GetProperty("context");
serverUrl = (string)pageContext.Invoke("getServerUrl");

Friday 14 September 2012


Mscrm 2011 Plugin basic code snippsets:

Code to extract service objects:

IPluginExecutionContext context =

                (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

 

            // Get a reference to the organization service.

            IOrganizationServiceFactory factory =

                (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

            IOrganizationService service = factory.CreateOrganizationService(context.UserId);

 

            // Get a reference to the tracing service.

            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

 

Getting input parameters:

if (context.InputParameters.Contains("Target") &&

    context.InputParameters["Target"] is Entity)

{

    // Obtain the target entity from the input parmameters.

    Entity entity = (Entity)context.InputParameters["Target"];

Shared variable:

context.SharedVariables.Add("PrimaryContact", (Object)contact.ToString());

if (context.SharedVariables.Contains("PrimaryContact"))

            {

                Guid contact =

                    new Guid((string)context.SharedVariables["PrimaryContact"]);

 

                // Do something with the contact.

            }

Image reading:

if (context.PreEntityImages.Contains("PreImage") &&
12
    context.PreEntityImages["PreImage"] is Entity)

 

13
{
14
    preMessageImage = (Entity)context.PreEntityImages["PreImage"];

 

15
}

 

 

Query expression class:

//  Create query using querybyattribute

    QueryByAttribute querybyexpression = new QueryByAttribute("account");

    querybyexpression.ColumnSet = new ColumnSet("name", "address1_city", "emailaddress1");

//  Attribute to query

    querybyexpression.Attributes.AddRange("address1_city");

//  Value of queried attribute to return

    querybyexpression.Values.AddRange("Detroit");

   

//  Query passed to the service proxy

    EntityCollection retrieved = _serviceProxy.RetrieveMultiple(querybyexpression);

  

//  Iterate through returned collection

    foreach (var c in retrieved.Entities)

    {

       System.Console.WriteLine("Name: " + c.Attributes["name"]);

       System.Console.WriteLine("Address: " + c.Attributes["address1_city"]);

       System.Console.WriteLine("E-mail: " + c.Attributes["emailaddress1"]);

    } 

-___________________________X___________________________

//  Query using ConditionExpression and FilterExpression

ConditionExpression condition1 = new ConditionExpression();

condition1.AttributeName = "lastname";

condition1.Operator = ConditionOperator.Equal;

condition1.Values.Add("Brown");           

 

FilterExpression filter1 = new FilterExpression();

filter1.Conditions.Add(condition1);

 

QueryExpression query = new QueryExpression("contact");

query.ColumnSet.AddColumns("firstname", "lastname");

query.Criteria.AddFilter(filter1);

 

EntityCollection result1 = _serviceProxy.RetrieveMultiple(query);

 

_________________x________________

QueryExpression contactquery = new QueryExpression

                        {

                            EntityName="contact",

                            ColumnSet = new ColumnSet("firstname", "lastname", "contactid")

                        };