Monday, November 2, 2009

Using xpath queries in BizTalk

We commonly use Xpath query to retrieve values within BizTalk. The few commonly used xpath queries in BizTalk are explained below. I am using the following XML to explain the xpath queries.



1) Retrieve a node with an attribute "@FieldName=EmailAddress" using xpath.

xpath(Message,"/*[local-name()='Line' and namespace-uri
()='http://www.alpha-helix.org.uk/eCommerce/OrderLine/v1']/*[local-name()='Optional' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/SalesLine/v1']/*[local-name()='Data' and @FieldName='EmailAddress']");

2) Retrieve attribute "@Value" from the message with "@FieldName"attribute and value "EmailAddress" using xpath.

string EmailAddress = xpath(Message,"string(/*[local-name()='Line' and namespace-uri
()='http://www.alpha-helix.org.uk/eCommerce/OrderLine/v1']/*[local-name()='Optional' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/SalesLine/v1']/*[local-name()='Data' and @FieldName='EmailAddress']/@Value)");

3) Retrieve the total count of node "Data" using xpath.

int x= xpath(Message,"number(count(/*[local-name()='Line' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/OrderLine/v1']/*[local-name()='Optional' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/SalesLine/v1']/*[local-name()='Data' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/OrderLine/v1']))");

4) Retrieving a single node from the node collection.

intLoopCount = intLoopCount+1; // position of the node in the list. A looping shape could be used to loop around each node in message.

string strExtractPath = System.String.Format("/*[local-name()='Line' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/OrderLine/v1']/*[local-name()='Optional' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/SalesLine/v1']/*[local-name()='Data' and namespace-uri()='http://www.alpha-helix.org.uk/eCommerce/OrderLine/v1' and position()={0}]",intLoopCount);

ExtractMessage = xpath(Message,strExtractPath);

where intLoopCount, is the position of the node "Data" in the above message. ExtractMessage will hold the node/message-part extracted from the actual message.

5) Retrieving a single attribute value from the message.

string fieldName = xpath(ExtractMessage,"string(//@FieldName)");

This will return single value if the attribute "@FieldName" is not repeated within the ExtractMessage.


Post any comments if you have. Good Luck!.

Wednesday, August 5, 2009

MS CRM : Creating bulk deletion job

Microsoft Dynamics CRM 4.0 allow users to bulk delete records using its interface, but is limited to a maximum of 250 records at a time. This is not a feasible solution if you have thousands of records to be deleted as a part of the campaign process.

CRM 4.0 supports bulk delete operation, but this functionality is not available out of box. You have to create an application which could perform this job using Dot Net.

The below code explains how you could perform a bulk delete operation on the leads entity.

You have to specify the Entity where the record need to be deleted and the Array of Lead Id's which needs to be deleted.

static void CreateBulkDeleteProcess()
{
try
{

// Create a query expression that retrieves all records for the entity.
QueryExpression qry = new QueryExpression();
qry.EntityName = EntityName.lead.ToString();
qry.ColumnSet = new AllColumns();

// Retrieve the accounts where the last name is not Cannon.
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "leadid";
condition.Operator = ConditionOperator.Equal;
condition.Values = new string[] { leadArray.ToString() };

// Build the filter based on the condition.
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.Conditions.Add(condition);
qry.Criteria = filter;

// Create a request.
BulkDeleteRequest request = new BulkDeleteRequest();
request.JobName = "Delete (" + iLoop +") + " lead records";
request.QuerySet = new QueryBase[] { qry };
request.SendEmailNotification = false;
request.ToRecipients = new Guid[0];
request.CCRecipients = new Guid[0];
request.RecurrencePattern = string.Empty;
request.StartDateTime = new CrmDateTime();
TimeSpan ts = new TimeSpan(0, 5, 0);
request.StartDateTime.Value = DateTime.Now.Add(ts).ToString("s");

// Execute the request.
BulkDeleteResponse response = (BulkDeleteResponse)oService.Execute(request);
Guid jobId = response.JobId;
Console.WriteLine("Job Id: " + jobId.ToString());
}
catch (Exception ex)
{
string sMsg = "Error creating deletion job for " + sEntityName + ": " + ex.Message;
throw new Exception(sMsg, ex);
}
}

We can schedule the start time for the bulk delete operation and leave it run during the off peak hours. Also an email notification to the user who needs to be intimated regarding this task could be allocated. If this process needs to be recurrent, a recurrent pattern could be defined.

This is really a cool way of deleting the records rather than going through the hurdles which CRM gives for bulk delete process.

How to read a excel/csv file using c#

Dot net provides different mechanism to read files. The problem occurs when you have large files to be read and processed. I had was wondering what difference a String and StringBuilder could make in the performance of manipulating a string record.

The real difference is too high while using String instead of StringBuilder and the system even reboots if the processing file size is too high.

public static string ReadCsvFile(string filePath)
{
StreamReader reader = null;
StringBuilder data = new StringBuilder();
string value = null;
using (reader = new StreamReader(filePath))
{
value = reader.ReadLine();
while (value!= null)
{
data.AppendLine(value);
}
}
return data. ToString ();
}


The Method above uses StreamReader, which is a light weight .net class which could read the CSV or Excel file line by line without giving the system too much hurdle.

The StringBuilder uses less memory by allocating the same memory for the new text appended to it without creating more memory space like the string.

This set of code runs very fast and without any memory leakage.

Send plain email messages using BizTalk SMTP Adapter

The new SMTP adapter provides the facility to send text/plain messages without using external classes or having more hazel.

Create a Message to be send which is of type System.String. Set the message SMTP values as follows in a Message Assignment shape.

EmailMessage = System.String.Empty;
EmailMessage(SMTP.Subject) = "Hello World!";
EmailMessage(SMTP.EmailBodyText) = "My Test Message"; // Text message body.
EmailMessage(SMTP.EmailBodyTextCharset) = "UTF-8";
EmailMessage(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";
SMTPSendPrt(Microsoft.XLANGs.BaseTypes.Address) = "mailto:bts@test.com";

In the above case I am using a dynamic send port, so I need to set the send port address before I send the message.

Microsoft.XLANGs.BaseTypes.Address , is used to set the address location of the message. You have to use "mailto:", as specified above in the address location.

If you have to send messages to more than one person, you can either set the "SMTP.CC" property, or you can use a ';' to delimit the email addresses.

SMTP.EmailBodyTextCharset is by default set as 'None', so has to be set explicitly to 'UTF-8'. Otherwise, BizTalk will throw strange run time errors.

Post any comments if you have. Enjoy!

Saturday, August 1, 2009

MS CRM : Update hotlist using plugin

Microsoft Dynamics CRM 4.0 offers a lot of functionality in terms of Customer relations management and sales process. It could be highly customised and flexible enough to satisfy the user requirement.

Microsoft Dynamics CRM 4.0, Plug ins are very powerful and are highly extensible within Dynamics CRM for overriding the limitations of Microsoft Dynamics CRM 4.0. The hotlist are one of the major component of Dynamics CRM, and it has some limitations in querying the information's required. Plug ins can be used to define the criteria and the use FetchXML query to get the information required.

Plug ins and IPluginExecutionContext

CRM SDK provides the list of Messages and entities which could be used for registering a plug in.

"Execute" is one of the Message type which could be used to register a plug in to trigger when an execute event is fired within CRM for a hotlist. The Execute message doesn't allow you to specify the primary or secondary entity, and will run within the logged in users context. There is Pre Stage and Post Stage stages for the pipeline execution and this could be used for both the Asynchronous and Synchronous execution modes.

The code below could be used to override the hotlist using the FetchXML and replacing it with the criteria required to return the exact result set. The
"context.InputParameters.Properties["FetchXml"]" gives you the currently executed query from CRM and this could be used if you just need to update the criteria only.


public class PeopleHotListViewsPlugin : IPlugin
{
public void Execute(IPluginExecutionContext context)
{
ICrmService vService = context.CreateCrmService(true);

if (context.InputParameters != null)
{
if (context.InputParameters.Properties.Contains("FetchXml"))
{

string fetch1 = @"
<fetch mapping='logical'>
<entity name='account'>
<attribute name='accountid'/>
<attribute name='name'/>
<link-entity name='systemuser' to='owninguser'>
<filter type='and'>
<condition attribute='lastname' operator='ne' value='Cannon' />
</filter>
</link-entity></entity></fetch>";

context.InputParameters.Properties["FetchXml"] = fetch1
}
}
}
}



The plug in should be registered using the Execute message as shown below.



The plug in will be executed each time a hotlist is called, but could be limited to the specific hotlist by matching the FetchXMl Entity node and adding a specific criteria to identify the hotlist.

Thanks
Abish Asharaf

Sunday, April 26, 2009

Active Directory and Dynamics CRM Users

Microsoft Dynamics CRM needs all users to be created within the Active Directory to access the CRM Application. Creating the users within the Active Directory and CRM is a real pain and You have create each users within the active directory and within the CRM seperatly. In case the number of users for the system is huge, then the Administrator need to do a hell lot of work to finish creating the user with a non-user friendly environment and assign the users business units and security roles seperatly. To reduce the manual process behind creating the users in CRM and Active directory, I have developed an application known as Crm Smart User which will provide you the facility of creating users within Active Directory and CRM.

The out of box CRM feature allows you to create bulk users, but it will not give you the provision to assign the users their Business Units and Security Roles.



The Crm Smart User provides you the additional functionality to create bulk users within Active Directory and CRM, and it assign the users the respective Business units and security privilages. Wow...So it's pretty cool..., yeah....

The massive work of creating the users in CRM and AD is reduced using this application. Now the Administrators can use this application to create users and enjoy the time.

The active directory domain name, organisation etc can be configured from the Application config file, so this application is easily customisable for use on different Domains and Servers.

The application also provides the facility to create a single user within the CRM and Active Directory. Users have the option to create users within CRM or in AD. The link to this applcation EXE : Crm Smart User Installation Kit.

The application is smart enough to identify the existing users within AD and CRM and avoid re-creatingthem within the application and AD. You can export the template used to create the users fom the last tab within the application. The first tab is a welcome screen and the second one is the bulk creation screen. Once the users are imported and created successfully, the system will update the status of the users on the Grid View as shown below.