Thursday, July 15, 2010

Attaching to Processes

Now that you have the plug-in registered, you are ready to start debugging. You need to attach to W3WP.exe(for synchronous services) to attach to plug-ins since they run within IIS. To attach to workflows you need to attach to the CRM async service which is Crmasyncservice.exe(for asynchronous services).

Hiding System defined Views in CRM 4.0

Some time user required to hide some system defined views from any entity in CRM 4.0,
to do this we need to create a plug-in.

For Example: hare you can hide "All My Leads" and "My Closed Leads" view's from my lead entity.

Use the following code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Metadata;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;

namespace HideViewsPlugin
{
public class HideViews : IPlugin
{
public void Execute(IPluginExecutionContext context)
{
// Query the SavedQueryBase table to retrieve the Query Id for an attribute savedqueryid
Guid[] Views = new Guid[] {
new Guid("5F001E93-3C6D-DE11-991A-0019B9F5ED8F"), //All My Leads
new Guid("36AA1011-4F6C-DE11-991A-0019B9F5ED8F"), //My Closed Leads
};

if (context.InputParameters != null && Views.Length > 0)
{
if (context.InputParameters.Properties.Contains(ParameterName.Query))
{
QueryExpression qe = (QueryExpression)context.InputParameters.Properties[ParameterName.Query];

//only apply this action if the query is for 'views' or saved queries
if (qe.EntityName == "savedquery")
{
if (qe.Criteria != null)
{
if (qe.Criteria.Conditions != null)
{
//Append more condition logic to the default query that's used by CRM. In this case, I filtered on the savedqueryid to exclude the views from the Ids identified above.
//This conditional expression hide only two defined Views
ConditionExpression queryCondition = new ConditionExpression("savedqueryid", ConditionOperator.NotIn, Views);


OR

//If you required to hide all the Views starting from a specific string then use the below defined ConditionExpression

/*The query is edited to look at views not starting with "Hidden" at the begining of the View Name*/

//ConditionExpression queryCondition = new ConditionExpression("name", ConditionOperator.NotLike, "Hidden%");


qe.Criteria.Conditions.Add(queryCondition);
context.InputParameters.Properties[ParameterName.Query] = qe;
}
}
}
}
}
}
}
}

Now register this plug-in and register one more Step for this plug-in,Parametters those required for step are given below:

Meggage: RetrieveMultiple
Primary Entity: savequery
Eventing Pipline: Pre Stage
Execution Mode: Synchronous
Step Deployment: Server
Triggering Pipeline: Parent Pipeline

Wednesday, July 14, 2010

Create a task through JavaScript after using Web Service in MS CRM 4.0

Some times we required to create a task for a user through JavaScript, you can do this by the following code

Here you can pass your Description ,Owner, Regarding,subject and created By parametters.

function CreateTask(MangerID,CreatedByID)
{
var CurrentQuoteID = crmForm.all.quotenumber.DataValue;
var xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
" <soap:Body>" +
" <Create xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <entity xsi:type=\"task\">" +
" <description>Your Message "+ CurrentQuoteID + "</description>" +
" <ownerid>" + MangerID + "</ownerid>" +
" <regardingobjectid type=\"quote\">" + crmForm.ObjectId + "</regardingobjectid>" +
" <subject>Your Subject "+ CurrentQuoteID + "</subject>" +
" <createdby>" + CreatedByID + "</createdby>" +
" </entity>" +
" </Create>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Create");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);

var resultXml = xmlHttpRequest.responseXML;
}

How can we use LookUpControl in my Custom page in CRM 4.0

I'm trying to replicate the functionality of this CRM 4.0 in my custom aspx page

<nobr>
<asp:TextBox ID="lookupresult" runat="server"></asp:TextBox>
<img src="/_imgs/btn_off_lookup.gif" onclick="ShowOwnerLookupDialog()" />

<script language="javascript">
function ShowOwnerLookupDialog()
{
var lookupItems = showModalDialog( '/_controls/lookup/lookupsingle.aspx?class=BasicOwner&objecttypes=8,2020&browse=0&ShowNewButton=1&ShowPropButton=1&DefaultType=0' , null, '' );
document.all.lookupresult.value = lookupItems.items[0].id;
}
</script>
</nobr>

Update Filtered lookup data in CRM 4.0

For this We have to pass fetch xml string using one of the parameters "search" recognised by the server otherwise exception is thrown (there is a way to disable parameters check through the registry setting
DisableParameterFilter, but it's easier without yet another undocumented setting).
Since we want to disable search functionality it makes sense to re-use search parameter.

Use the following code:

This line of code using for single entity
//The attribute where lookup is attached
var field = crmForm.all.pricelevelid;

// Ensure that search box is not visible in a lookup dialog
field.lookupbrowse = 1;
// Pass fetch xml through search value parameter
field.AddParam("search",
"<fetch mapping='logical'><entity name='pricelevel'>"
+ "<filter><condition attribute='name' operator='eq' value='pricelist name' /></filter></entity></fetch>");


This line of code using for multiple entity
//Lookup will show all the Child users of current loggedIn user

//Return all child users
var targetUserUnits = GetChildusers() //for eg: <value>"+Value1+"</value><value>"+Value2+"</value>
//The attribute where lookup is attached
var field = crmForm.all.new_userid;
//Ensure that search box is not visible in a lookup dialog
field.lookupbrowse = 1;

field.AddParam("search",
"<fetch mapping='logical'><entity name='systemuser'>"
+"<all-attributes/>"
+"<link-entity name='new_nesteduser' from='new_userid' to='systemuserid'>"
+"<filter type='and'><condition attribute='new_lft' operator='between'>"
+targetUserUnits
+"</condition></filter></link-entity></entity></fetch>");

Unsupported
You can manage it from lookup form means if this parameter contains any value then apply this filter otherwise use as origional.
to do this open the page "C:\Program Files\Microsoft Dynamics CRM\CRMWeb\_controls\lookup\lookupsingle.aspx " and change it accordingly as required.

For Eg.

void crmgrid_PreRender( object sender , EventArgs e )
{
// As we don't want to break any other lookups, ensure that we use workaround only if
// search parameter set to fetch xml.
<strong>if (crmGrid.Parameters["search"] != null && crmGrid.Parameters["search"].StartsWith("<fetch"))
{
crmGrid.Parameters.Add("fetchxml", crmGrid.Parameters["search"]);
// searchvalue needs to be removed as it's typically set to a wildcard '*'
crmGrid.Parameters.Remove("searchvalue");
// Icing on a cake - ensure that user cannot create new contact outside of the account
// and then select it.
this._showNewButton = false;
} </strong>
}

Expose the toggling function at the window level in CRM 4.0

After create a function in page load event of any entity in CRM and tried to call it from onSave or any attribute OnChange event
then you don't required to type the same function again and again just toggle this function at the bottom of pageLoad
event, to do this use the following code

//Expose the toggling function at the window level
this.functionName = functionName;

Monday, July 12, 2010

Determine Space Available/Used for Entities

Determine Space Available for your Entity

If you decide to add a custom attribute to an entity, you can determine if there is
space available for the attribute in the entity's extension table by running this
Transact-SQL query on the _CRM database.Use this following query:

select EntityName=e.name,Bytes_Remaining=8060-(Sum(a.length))
from entity e join attribute a on e.entityid=a.entityid
where a.iscustomerfield=1 and a.islogical=0
group by e.Name


Determine Space Used for your Entity

Alternatively, you can determine the number of bytes already used by custom
attributes for an entity by running this Transact-SQL query on the
_CRM database.Use this following query:

select EntityName=e.Name,Physical_size=Sum(a.length)
from entity e join attribute a on e.entityid=a.entityid
where a.iscustomerfield=1 and a.islogical=0
group by e.Name

Split the String values with a special character in MS Flow to convert this into Array

 Many times we have a requirement to prepare the Mailing address for some of the documents, suppose there are Address Line1, Address Line2, ...