Debugging WCF Rest Service

 

Here we will see how we can debug a WCF Rest Service using Advanced Rest Client (Chrome Extensions)

https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

Suppose this is our sample WCF Rest Service we want to debug

(Please check the following post on details of creating a WCF rest service <<earlier posts link>>)

The Advanced Rest Client interface

  • Here we have specified Url of the Rest Service
  • The Post Data to be passed
  • The response that we got back

Now to debug our WCF Rest Service set the debugging point and attach the debugger to the Advanced Rest Client process.

 

Run the WCF Service in the Visual Studio.

Specify the WCF Rest Service URL and Post Data expected and then click on Send on the Advanced Rest Client.

The debugging will start

Hope it helps.

Advertisements

Debugging online plugin in CRM 2011

Hi,

Let us take a simple plugin to understand the debugging process. We are throwing the exception to get the profile which we will use for debugging.


public
class
Class1 : IPlugin

{


public
void Execute(IServiceProvider serviceProvider)

{


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

 


Entity entity;


// Check if the input parameters property bag contains a target


// of the create operation and that target is of type Entity.


if (context.InputParameters.Contains(“Target”) && context.InputParameters[“Target”] is
Entity)

{


// Obtain the target business entity from the input parameters.

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

 


// Verify that the entity represents a contact.


if (entity.LogicalName != “contact”) {

 


throw
new
InvalidPluginExecutionException();


return;

}

}

 

}

}

We need to use the latest plugin registration tool that will have the option of Installing Profiler which we will use. Get it from the latest SDK of CRM 2011.

Register the plugin (debug version) and corresponding step using plugin registration tool.

Select Install Profiler in Plugin Registration tool and wait till the installation is complete.


Select the Step in Plugin and Click Profile in the tool

Select Ok in the dialog box

Open CRM and perform the step that will run the plugin and throw the exception.

Download the log file.

Open Visual Studio and attach debugger to PluginRegistrationTool.exe

Go back to Plugin Registration tool, select the step and select Debug from the tool bar.

 

Specfiy the log file in the Profile location and plugin assembly that is in debug folder.

Click on Start Execution to start debugging

Happy debugging J

[How To]:Converting a WCF Service to REST Enabled – Part 1

Below are the steps to convert make the service REST enabled :

Step 1 :

In IserviceRequestManager.cs, replace the [Operation Contract] with [WebGet] and add reference “System.ServiceModel.Web”

Step 2 :

In ServiceRequestManager.svc markup, add the attribute “Factory=”System.ServiceModel.Activation.WebServiceHostFactory”.

As shown below :

<%@
ServiceHost
Language=”C#”
Debug=”true”
Service=”XYZ.ServiceManagement.Services.ServiceRequestManager”
CodeBehind=”ServiceRequestManager.svc.cs”
Factory=”System.ServiceModel.Activation.WebServiceHostFactory”
%>

Step 3 :

In web.config within the <system.ServiceModel> add the following configuration :

“<standardEndpoints>
<webHttpEndpoint>
<!– the “” standard endpoint is used by WebServiceHost for auto creating a web endpoint. –>
<standardEndpoint name=”” helpEnabled=”true”/>
</webHttpEndpoint>
</standardEndpoints>”

As shown below :

Happy Exploring J

Subject Records Imported to Custom Entity in CRM

In my project,there was a requirement for creating a custom entity which will have the same records as present in the subject entity.So I had to create a tool to import the subject records to the custom entity created in CRM(here named as : DecisionTreeNode)

Here in this article I will be demonstrating the steps for creating the tool which imports subject record to the custom entity.Below are the steps:

Step 1:

Create a new windows application with the following form design:

Step 2:

In the Program.cs ,it will have the following code :


static  class Program   {
///  <summary>
/// The main entry point for the application.
///  </summary>
[STAThread]
static  void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new  Utility());
}
}

Step 3 :

Add a new cs file and write the following code:

On click of the Retrieve button:

private  void ButtonSubjects_Click(object sender, EventArgs e)
{
try
{
Microsoft.Crm.Sdk.CrmAuthenticationToken token = new Microsoft.Crm.Sdk.CrmAuthenticationToken();
token.OrganizationName = ConfigurationManager.AppSettings["organizationName"];
string crmServerUrl = ConfigurationManager.AppSettings["crmServiceUrl"];
Microsoft.Crm.SdkTypeProxy.CrmService service = new Microsoft.Crm.SdkTypeProxy.CrmService();
if (crmServerUrl != null && crmServerUrl.Length > 0)
{
UriBuilder builder = new  UriBuilder(crmServerUrl);
builder.Path = "//MSCRMServices//2007//CrmService.asmx";
service.Url = builder.Uri.ToString();
}
service.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["username"], ConfigurationManager.AppSettings["password"], ConfigurationManager.AppSettings["Domain"]);
service.CrmAuthenticationTokenValue = token;
this.UpdateChildRecords(service);
labelMessage.Text = "Records imported to Decision TreeNode successfully.";
labelMessage.ForeColor = Color.Green;
labelMessage.Visible = true;
}
catch (Exception)
{
labelMessage.Text = "Records could not be imported!";
labelMessage.ForeColor = Color.Red;
labelMessage.Visible = true;
throw;
}
}

Which calls UpdateChild Records function

public  void UpdateChildRecords(CrmService crmService)
{
////string parentName = string.Empty;
QueryExpression query = new QueryExpression();
//// Setup the query for the new_decisiontreenode entity
query.EntityName = "subject";
//// Specify the columns to retrieve
ColumnSet columns = new ColumnSet();
columns.AddColumns(new  string[] { "subjectid", "parentsubject", "title", "description" });
query.ColumnSet = columns;
RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
retrieveMultipleRequest.ReturnDynamicEntities = true;
retrieveMultipleRequest.Query = query;
RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(retrieveMultipleRequest);
BusinessEntityCollection businessUpdate = retrieved.BusinessEntityCollection;
//// Execute the query and return the result
foreach (BusinessEntity bechild in businessUpdate.BusinessEntities)
{
string parentId = string.Empty;
string currentTitle = string.Empty;
string fullName = string.Empty;
string formattedName = string.Empty;
DynamicEntity de = (DynamicEntity)bechild;
if (de.Properties.Contains("parentsubject"))
{
parentId = ((Microsoft.Crm.Sdk.CrmReference)de.Properties["parentsubject"]).Value.ToString();
currentTitle = de.Properties["title"].ToString();
fullName = this.GetParentName(crmService, ((Key)de.Properties["subjectid"]).Value.ToString()) + "." + currentTitle;
formattedName = fullName.Remove(0, 1);
}
string subjectId = ((Key)de.Properties["subjectid"]).Value.ToString();
string title = de.Properties["title"].ToString();
var lookupPropertySubject = new LookupProperty();
lookupPropertySubject.Name = "new_subject";
var lookupSubject = new Lookup();
lookupSubject.type = "subject";
lookupSubject.Value = new  Guid(subjectId);
if (string.IsNullOrEmpty(formattedName))
{
lookupSubject.name = title;
}
else
{
lookupSubject.name = formattedName;
}
lookupPropertySubject.Value = lookupSubject;
CreateNewRecord(subjectId, parentId, lookupPropertySubject, crmService);
}
public  string GetParentName(CrmService crmService, string subjectId)
{
////string parentName = string.Empty;
QueryExpression query = new QueryExpression();
//// Setup the query for the new_decisiontreenode entity
query.EntityName = "subject";
//// Specify the columns to retrieve
ColumnSet columns = new ColumnSet();
columns.AddColumns(new  string[] { "subjectid", "parentsubject", "title", "description" });
////ColumnSet columns= new AllColumns();
query.ColumnSet = columns;
//// Create the new_parentid condition
ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "subjectid";
condition1.Operator = ConditionOperator.Equal;
condition1.Values = new  object[] { subjectId };
////Create the FilterExpression
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.Conditions.Add(condition1);
query.Criteria = filter;
RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
retrieveMultipleRequest.ReturnDynamicEntities = true;
retrieveMultipleRequest.Query = query;
RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(retrieveMultipleRequest);
BusinessEntityCollection businessUpdate = retrieved.BusinessEntityCollection;
BusinessEntity businessEntity = businessUpdate.BusinessEntities[0];
//// Execute the query and return the result
DynamicEntity de = (DynamicEntity)businessEntity;
string fullName = string.Empty;
if (de.Properties.Contains("parentsubject"))
{
fullName = this.GetParentName(crmService, ((Microsoft.Crm.Sdk.CrmReference)de.Properties["parentsubject"]).Value.ToString()) + "." + ((Microsoft.Crm.Sdk.CrmReference)de.Properties["parentsubject"]).name.ToString();
}
return fullName;
}

Step 4 :
Creating new records in the custom entity:

</span>
public  static  void CreateNewRecord(string subjectId, string parentId, LookupProperty subject, CrmService crmService)
{
if (crmService != null && subject != null)
{
if (!IsIdExists(subjectId, crmService))
{
var entityDecisionTreeNode = new DynamicEntity();
entityDecisionTreeNode.Name = "new_decisiontreenode";
var boolToBeEscalated = new CrmBooleanProperty();
boolToBeEscalated.Name = "new_tobeescalatedflag";
boolToBeEscalated.Value = new CrmBoolean();
boolToBeEscalated.Value.Value = true;
var newSubjectId = new StringProperty("new_subjectid", subjectId);
var newParentId = new StringProperty("new_parentid", parentId);
var subjectName = new LookupProperty("new_subject", subject.Value);
var subjectTitle = new StringProperty("new_title", subject.Value.name);
entityDecisionTreeNode.Properties.Add(newSubjectId);
entityDecisionTreeNode.Properties.Add(newParentId);
entityDecisionTreeNode.Properties.Add(boolToBeEscalated);
entityDecisionTreeNode.Properties.Add(subjectName);
entityDecisionTreeNode.Properties.Add(subjectTitle);
var targetCreate = new TargetCreateDynamic();
targetCreate.Entity = entityDecisionTreeNode;
//// Create the request object.
var create = new CreateRequest();
create.Target = targetCreate;
//// Execute the request.
crmService.Execute(create);
}
}
}

 

The above function turn calls IsIdExists function,which checks duplicate records are not created:

public static bool IsIdExists(string subjectId, CrmService crmService)
{
QueryExpression query = new QueryExpression();
//// Setup the query for the new_decisiontreenode entity
query.EntityName = "new_decisiontreenode";
//// Specify the columns to retrieve
ColumnSet columns = new ColumnSet();
columns.AddColumns(new string[] { "new_subjectid" });
query.ColumnSet = columns;
//// Create the new_parentid condition
ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "new_subjectid";
condition1.Operator = ConditionOperator.Equal;
condition1.Values = new object[] { subjectId };
////Create the FilterExpression
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.Conditions.Add(condition1);
query.Criteria = filter;
RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest();
retrieveMultipleRequest.ReturnDynamicEntities = true;
retrieveMultipleRequest.Query = query;
RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)crmService.Execute(retrieveMultipleRequest);
BusinessEntityCollection businessUpdate = retrieved.BusinessEntityCollection;
if (businessUpdate.BusinessEntities.Count > 0)
{
return true;
}
else
{
return false;
}
}

Step 5:
On Button Close click the following code has to be added:

private void ButtonClose_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Utility_Load(object sender, EventArgs e)
{
labelMessage.Visible = false;
}

Now just build and run the exe,you will find the records created automatically to your custome entity.
Hope this helps and let me know if you face any issues.
Happy Coding 🙂

TreeView – from datatables

I will demonstrate the basics for creating a treeview from2 different tables:

Let’s take 2 datatable for example:

DataTable table = new DataTable();
table.Columns.Add("QueueID", typeof(string));
table.Columns.Add("Queue", typeof(string));
table.Rows.Add("1", "Queue 1");
table.Rows.Add("2", "Queue 2");
table.Rows.Add("3", "Queue 3");
table.Rows.Add("4", "Queue 4");
table.Rows.Add("5", "Queue 5");
table.Rows.Add("6", "Queue 6");
table.Rows.Add("7", "Queue 7");
table.Rows.Add("8", "Queue 8");
DataTable table1 = new DataTable();
table1.Columns.Add("QueueID", typeof(string));
table1.Columns.Add("Subject", typeof(string));
table1.Rows.Add("1", "Subject 1");
table1.Rows.Add("1", "Subject 2");
table1.Rows.Add("2", "Subject 1");
table1.Rows.Add("2", "Subject 2");
table1.Rows.Add("2", "Subject 3");
table1.Rows.Add("2", "Subject 4");
table1.Rows.Add("3", "Subject 1");
table1.Rows.Add("3", "Subject 2");

Now,we need to create a relation between those two datatables :

DataSet ds = new  DataSet();
ds.Tables.Add(table);
ds.Tables.Add(table1);
ds.Relations.Add("Children", table.Columns[0], table1.Columns[0]);//define parent child relation in dataset

We will now represent the following relation in a Treeview with Queue as the Parent Node and the Subjects as the child node.

if (ds.Tables[0].Rows.Count > 0)
{
trv.Nodes.Clear();
Int32 count = 0;
foreach (DataRow masterRow in ds.Tables[0].Rows)
{
TreeNode masterNode = new  TreeNode((String)masterRow[1], Convert.ToString(masterRow[0]));
masterNode.ImageUrl =  @"Images\QueueuImage.png";
trv.Nodes.Add(masterNode);
foreach (DataRow childRow in masterRow.GetChildRows("Children"))
{
TreeNode childNode = new  TreeNode((String)childRow[1], Convert.ToString(childRow[1]));
childNode.ImageUrl = @"Images\Subject.png";
masterNode.ChildNodes.Add(childNode);
count++;
}
}
trv.ExpandAll();
}

Below is the snapshot of the treeview that will be created by the above given code snippets.

Treeview Display – Data From CRM

Here in this article I have posted the code snippet for displaying the QueueView(of CRM) in an Asp.Net Web Page.

Step 1 :

Fetching the data from the CRM

const String fetchXml = @"<fetch mapping=""logical"" count=""50"" version=""1.0"">
<entity name=""queue""><attribute name=""name"" /><attribute name=""primaryuserid"" />
<attribute name=""queueid"" /><attribute name=""queuetypecode"" />
<filter type=""or""><condition attribute=""primaryuserid"" operator=""eq-userid"" />
<condition attribute=""queuetypecode"" operator=""eq"" value=""1"" /></filter>
<link-entity name=""queueitem"" from=""queueid"" to=""queueid"">
<link-entity name=""incident"" from=""incidentid"" to=""objectid"">
<attribute name=""incidentid"" /><attribute name=""subjectid"" />
<attribute name=""title"" />
<link-entity name=""subject"" from=""subjectid"" to=""subjectid"">
<attribute name=""subjectid"" />
<attribute name=""title"" />
</link-entity></link-entity></link-entity></entity></fetch>";
var fetchResponse = string.Empty;
var crmService = new CrmService();
try
{
crmService = new CrmService();
crmService.Url = "http://<servername>/mscrmservices/2007/crmservice.asmx";
crmService.Credentials = CredentialCache.DefaultNetworkCredentials;
var token = new CrmAuthenticationToken {AuthenticationType = 0, OrganizationName = "<organizationname>"};
crmService.CrmAuthenticationTokenValue = token;
crmService.UnsafeAuthenticatedConnectionSharing = true;
 

Step 2 :

QueueView as in CRM with “My Work” and Public “Queue”

#region QueueView
var request = new WhoAmIRequest();
var user = (WhoAmIResponse) crmService.Execute(request);
var condition = new ConditionExpression {AttributeName = "queuetypecode", Operator = ConditionOperator.In, Values = new string[] {"2", "3"}};
/// Set the condition for the retrieval
var conditionUser = new ConditionExpression {AttributeName = "primaryuserid", Operator = ConditionOperator.In, Values = new string[] {user.UserId.ToString()}};
// Set the condition for the retrieval
// Create the FilterExpression.
var filter = new FilterExpression {FilterOperator = LogicalOperator.And};
// Set the properties of the filter.
filter.Conditions.Add(conditionUser);
filter.Conditions.Add(condition);

var queryQueue = new QueryExpression{ EntityName = EntityName.queue.ToString(), ColumnSet = new AllColumns(), Criteria = filter};
BusinessEntityCollection queueFilter = crmService.RetrieveMultiple(queryQueue);
// Define your Dataset and DataTable
var dataSetQueue = new DataSet();
var userQueues = new DataTable();
//// Set Column headers for the DataTable
userQueues.Columns.Add("QueueName");
userQueues.Columns.Add("QueueID");
////Iterate the BusinessEntityColleciton
foreach (BusinessEntity queues in queueFilter.BusinessEntities)
 {var ic = (queue) queues;
DataRow dr = userQueues.NewRow();
dr["QueueName"] = ic.name;
 dr["QueueID"] = "{" + ic.queueid.Value + "}";
userQueues.Rows.Add(dr);                 }
dataSetQueue.Tables.Add(userQueues);
#endregion

#region FetchXml
fetchResponse = crmService.Fetch(fetchXml);
var doc = new XmlDocument();
 doc.LoadXml(fetchResponse);
 var docReader = new XmlNodeReader(doc);
//read into dataset
var dataSet = new DataSet();
dataSet.ReadXml(docReader);

var dt = dataSet.Tables[1];
DataTable uniqueQueues = dt.DefaultView.ToTable(true, "queueid", "name");
uniqueQueues.Columns.Add("QueueCaseCount");
var uniqueQueuesSubjects = dt.DefaultView.ToTable(true, "queueid", "subjectid.subjectid");
uniqueQueuesSubjects.Columns.Add("CaseCount");
uniqueQueuesSubjects.Columns.Add("Subject Title");

foreach (DataRow dr in uniqueQueues.Rows)
{
int cc = 0;
for (var j = 0; j < dt.Rows.Count; j++)
{
if (dr[0].ToString() == dt.Rows[j].ItemArray[2].ToString())
{ cc++;}}

dr[2] = cc;}
foreach (DataRow dr in uniqueQueuesSubjects.Rows)
{
var cc = 0;
for (var j = 0; j < dt.Rows.Count; j++)
 {
if (dr[0].ToString() == dt.Rows[j].ItemArray[2].ToString() && dr[1].ToString() == dt.Rows[j].ItemArray[5].ToString())
{
 cc++;
dr[3] = dt.Rows[j].ItemArray[6]; //subject Title }}

dr[2] = cc;}
var assignedCnt = 0;
var wipCnt = 0;
for (var i = 0; i < uniqueQueues.Rows.Count; i++)
 {
if (uniqueQueues.Rows[i].ItemArray[1].ToString().Contains("private queue"))
{
uniqueQueues.Rows[i][1] = "Assigned";
assignedCnt++;
}

if (uniqueQueues.Rows[i].ItemArray[1].ToString().Contains("WIP Bin queue"))
 {
uniqueQueues.Rows[i][1] = "In Progress";
wipCnt++; }}

if (assignedCnt == 0)
 {uniqueQueues.Rows.Add(userQueues.Rows[0].ItemArray[1], "Assigned", "0"); }

if (wipCnt == 0) {
uniqueQueues.Rows.Add(userQueues.Rows[1].ItemArray[1], "In Progress", "0"); }

var asg = 0;
var prg = 0;

for (var i = 0; i < uniqueQueuesSubjects.Rows.Count; i++)
 {
if (userQueues.Rows[0].ItemArray[1].ToString().ToUpper() == uniqueQueuesSubjects.Rows[i].ItemArray[0].ToString())
{ asg++;}
if (userQueues.Rows[1].ItemArray[1].ToString().ToUpper() ==  uniqueQueuesSubjects.Rows[i].ItemArray[0].ToString())
{ prg++;}}
if (asg == 0){
uniqueQueuesSubjects.Rows.Add(userQueues.Rows[0].ItemArray[1], string.Empty, 0, "No Subjects");}
if (prg == 0)
{uniqueQueuesSubjects.Rows.Add(userQueues.Rows[1].ItemArray[1], string.Empty, 0, "No Subjects");}
uniqueQueuesSubjects = uniqueQueuesSubjects.DefaultView.ToTable(true, "queueid", "subjectid.subjectid", "CaseCount", "Subject Title");
var myWorkQueue = new DataTable("myWorkQueue");
myWorkQueue.Columns.Add("queueid");
myWorkQueue.Columns.Add("name");
myWorkQueue.Columns.Add("QueueCaseCount");
var myWorkSubject = new DataTable("myWorkSubject");
myWorkSubject.Columns.Add("queueid");
myWorkSubject.Columns.Add("subjectid.subjectid");
myWorkSubject.Columns.Add("CaseCount");
myWorkSubject.Columns.Add("Subject Title");
for (var i = 0; i < uniqueQueues.Rows.Count; i++)
{if (uniqueQueues.Rows[i].ItemArray[1].ToString() == "Assigned")
{myWorkQueue.Rows.Add(uniqueQueues.Rows[i].ItemArray[0], uniqueQueues.Rows[i].ItemArray[1],uniqueQueues.Rows[i].ItemArray[2]);
uniqueQueues.Rows.RemoveAt(i);}
if (uniqueQueues.Rows[i].ItemArray[1].ToString() == "In Progress")
{ myWorkQueue.Rows.Add(uniqueQueues.Rows[i].ItemArray[0], uniqueQueues.Rows[i].ItemArray[1], uniqueQueues.Rows[i].ItemArray[2]);
uniqueQueues.Rows.RemoveAt(i); }}
for (int i = 0; i < uniqueQueuesSubjects.Rows.Count; i++)  {
if (uniqueQueuesSubjects.Rows[i].ItemArray[0].ToString() == myWorkQueue.Rows[0].ItemArray[0].ToString() || uniqueQueuesSubjects.Rows[i].ItemArray[0].ToString() == myWorkQueue.Rows[1].ItemArray[0].ToString())
{myWorkSubject.Rows.Add(uniqueQueuesSubjects.Rows[i].ItemArray[0], uniqueQueuesSubjects.Rows[i].ItemArray[1], uniqueQueuesSubjects.Rows[i].ItemArray[2], uniqueQueuesSubjects.Rows[i].ItemArray[3]);
uniqueQueuesSubjects.Rows.RemoveAt(i);
i--;}}
myWorkQueue.DefaultView.Sort = "QueueCaseCount DESC";
DataTable dvmyWorkQueue = myWorkQueue.DefaultView.ToTable();
myWorkSubject.DefaultView.Sort = "CaseCount DESC";
DataTable dvmyWorkSubject = myWorkSubject.DefaultView.ToTable();
uniqueQueues.DefaultView.Sort = "QueueCaseCount DESC";
DataTable dvuniqueQueues = uniqueQueues.DefaultView.ToTable();
uniqueQueuesSubjects.DefaultView.Sort = "CaseCount DESC";
DataTable dvuniqueQueuesSubjects = uniqueQueuesSubjects.DefaultView.ToTable();

#region Treeview For My Work

var dsMyWork = new DataSet();
dsMyWork.Tables.Add(dvmyWorkQueue);
dsMyWork.Tables[0].TableName = "myWorkQueue";
dsMyWork.Tables.Add(dvmyWorkSubject);
dsMyWork.Tables[1].TableName = "myWorkSubject";

dsMyWork.Relations.Add("Children", dvmyWorkQueue.Columns[0], dvmyWorkSubject.Columns[0]);
//define parent child relation in dataset

if (dsMyWork.Tables[0].Rows.Count > 0)
{trvMyWork.Nodes.Clear();
var myWorkNode = new TreeNode("My Work") {ImageUrl = @"Images\QueueuImage.png"};

trvMyWork.Nodes.Add(myWorkNode);
foreach (DataRow masterRow in dsMyWork.Tables[0].Rows)
{ var masterNode = new TreeNode((String) masterRow[1], Convert.ToString(masterRow[0])){Text = masterRow[1].ToString() + "(" + masterRow[2].ToString() + ")", ImageUrl = @"Images\MyWorkQueue.png"};
myWorkNode.ChildNodes.Add(masterNode);
foreach (var childRow in masterRow.GetChildRows("Children")){
var childNode = new TreeNode((String) childRow[3], Convert.ToString(childRow[3]));
if (childRow[3].ToString() == "0"){
childNode.Text = "No Records in Queue";}
else{ childNode.Text = string.Format("{0} ({1})", childRow[3].ToString(), childRow[2].ToString());
childNode.ImageUrl = @"Images\Subject.png";}
masterNode.ChildNodes.Add(childNode);}  }
trvMyWork.ExpandAll();}
#endregion

#region Treeview For Queues
var ds = new DataSet();
ds.Tables.Add(dvuniqueQueues);
ds.Tables[0].TableName = "dvuniqueQueues";
ds.Tables.Add(dvuniqueQueuesSubjects);
ds.Tables[1].TableName = "dvuniqueQueuesSubjects";
ds.Relations.Add("Children", dvuniqueQueues.Columns[0], dvuniqueQueuesSubjects.Columns[0]);
//define parent child relation in dataset
if (ds.Tables[0].Rows.Count > 0) {
trv.Nodes.Clear();
foreach (DataRow masterRow in ds.Tables[0].Rows) {
var masterNode = new TreeNode((String) masterRow[1], Convert.ToString(masterRow[0])){
Text = masterRow[1].ToString() + "(" + masterRow[2] + ")",ImageUrl = @"Images\QueueuImage.png"};
trv.Nodes.Add(masterNode);
foreach (DataRow childRow in masterRow.GetChildRows("Children")) {
var childNode = new TreeNode((String) childRow[3], Convert.ToString(childRow[3]));
if (childRow[3].ToString() == "0"){
childNode.Text = @"No Records in queue"; }
else  {
childNode.Text = string.Format("{0} ({1})", childRow[3].ToString(), childRow[2].ToString());
childNode.ImageUrl = @"Images\Subject.png"; }
masterNode.ChildNodes.Add(childNode); } }
trv.ExpandAll(); }
#endregion
}
catch (SoapException ex)
 {
var errMSg = ex.Detail.InnerXml;
}
#endregion

This will help you create the queueview similar to the one in CRM and this can be used as custom pages in CRM.
Thanks 🙂

Windows Service with Timer based on CRM configuration value

Here I will be describing about a scenario where a windows service will perform a task based on time configured in CRM.

Please find the below problem statement:

Create a custom entity named “Configuration” which will hold the interval time at which the windows service should fire an email. Following are the steps to solve the problem:

1 . Browse to CRM>Settings>Customization>Customize Entities>Configuration:

2. Click on Add and enter the following values and click on OK button:

3. Click on “Save and Close” and Publish.

4. Goto >Workspace>Extensions >Configuration

5. Click on New and enter the following values:

6. Click on Save and Close.

7. Please refer the link for how to create a windows service.

Now in your existing windows service add the following code:

public class Program : ServiceBase{
private Timer timer = null;
private Microsoft.Crm.SdkTypeProxy.CrmService service = new Microsoft.Crm.SdkTypeProxy.CrmService();
private string[] timeValues = null;
public Program()
{
this.ServiceName = "EmailService";
this.GetCrmService();
//// Set the timer to fire every sixty seconds
//// so 1000 = 1 second. )
this.timer = new Timer(60000);
this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.TimerElapsed);
}
public static void Main()
{
ServiceBase.Run(new Program());
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
this.timeValues = <span style="background-color: yellow;">GetEmailConfiguration(this.service)</span>;//this method returns the time interval value form CRM
this.timer.Start();
}
protected override void OnStop()
{
base.OnStop();
this.timer.Stop();
}
protected void TimerElapsed(object sender, ElapsedEventArgs e)
{
foreach (string times in this.timeValues)
{
if (DateTime.Now.ToString("HH:mm", CultureInfo.InvariantCulture) == times)
{

//Code for sending Email based on the values in CRM

}
}
}

8. Build the solution in release mode and Go to the Release Folder.

9. Change the configuration as per the requirements in the EmailService.exe.config.

10. Goto command prompt and copy the following:

 cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319 

11. Enter and then again copy the following:

Installutil.exe <path of the exe>\ <name of the .exe file>

12. Go to services.msc and double-click on “EmailService

13. Go to “LogOn” tab and select “This Account” and give the appropriate credentials.

14. Right Click on the service and start the service as shown below:

15.  Now the service has started and will send the email at specified intervals to the respective recipients.

Happy Coding 🙂