Tuesday 12 July 2011

CRM 2011 custom workflow: Cancelling an Activity and Adding Note to it

After a lot of hardship i have come up with workflow which does a very straight forward thing. it looks for an activity with a certain subject line. when it finds the activity in question, if the activity has not been cancelled, it cancels it after adding a note to it. i have done it for all the activity types. to avoid duplication i am just sticking with the first two (task and email). Since i'm copy-pasting, there is a chance that there will be unmatched parenthesis.

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//my usings
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using System.Collections.ObjectModel;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Deployment;
using Microsoft.Xrm.Sdk.XmlNamespaces;
using System.Activities.Debugger;
using Microsoft.IdentityModel.Protocols.WSTrust;
namespace Don_Det_onUpdate
{
public sealed class DonarDetailsOnApproved : CodeActivity
{
[Input("Type of Activity")]
[RequiredArgument]
[Default("4212")]
[AttributeTarget("activitypointer","activitytypecode")]
public InArgument TypeOfActivity { get; set; }
[Input("Subject Line")]
[RequiredArgument]
public InArgument SubjectLine { get; set; }
protected override void Execute(CodeActivityContext context)
{
IWorkflowContext con = context.GetExtension();
IOrganizationServiceFactory objIOrganizationServiceFactory = context.GetExtension();
IOrganizationService service = objIOrganizationServiceFactory.CreateOrganizationService(con.UserId);
OptionSetValue ActType = TypeOfActivity.Get(context);
try
{
var crm = new XrmServiceContext(service);
Int16? ActivityId = Convert.ToInt16(ActType.Value);
// 07 july by imran
if (ActivityId.HasValue)
{
switch (ActivityId)
{
// this is a task...
case 4212:
var TaskList = crm.TaskSet.Where(t => t.Subject == SubjectLine.Get(context).ToString() && t.StateCode != TaskState.Canceled);
foreach (Task tsk in TaskList)
{
var note = new Annotation
{
Subject = "System generated note",
NoteText = "This activity is cancelled and no longer required.",
ObjectId = new EntityReference(tsk.LogicalName, tsk.Id),
ObjectTypeCode = tsk.GetType().ToString().ToLower()
};
crm.AddObject(note);
crm.UpdateObject(tsk);
crm.SaveChanges();
var k = new SetStateRequest
{
EntityMoniker = new EntityReference(tsk.LogicalName, tsk.Id),
State = new OptionSetValue(2),
Status = new OptionSetValue(-1)
};
crm.Execute(k);
break;
}
break;
case 4202: // email
var EmailList = crm.EmailSet.Where(t => t.Subject == SubjectLine.Get(context).ToString() && t.StateCode != EmailState.Canceled);
foreach (Email eml in EmailList)
{
var note = new Annotation
{
Subject = "System generated note",
NoteText = "This activity is cancelled and no longer required.",
ObjectId = new EntityReference(eml.LogicalName, eml.Id),
ObjectTypeCode = eml.GetType().ToString().ToLower()
};
crm.AddObject(note);
crm.UpdateObject(eml);
crm.SaveChanges();
var k = new SetStateRequest
{
EntityMoniker = new EntityReference(eml.LogicalName, eml.Id),
State = new OptionSetValue(2),
Status = new OptionSetValue(-1)
};
crm.Execute(k);
break;
}
    break;
   default:
break;
}
}
}
catch (Exception ex)
{
}
}
}
}         



      

the question that pops up as soon as you come across to the code. that how the hell you come across to the activitytype (which i used in switch). i am damn sure there are lots of smart ways to find them. but i debugged and looked for the value. (silly me...)

Sunday 10 July 2011

System.Configuration.ConfigurationSettings.AppSettings’ is obsolete: ‘This method is obsolete, it has been replaced by System.Configuration!System.Con

one of the great ways to save machine/server specific info into application is to save it in app.config or web.config file. these config files traditionally stores connection informations to the database. But how about if you want to store some other things like, the location of input and output folder for files.
below is a code snippet of two file locations that i am storing into app.config file
as you can probably understand i have created two key value pairs named "Source" and "Assembly" which stores a file location of my computer. now question is how to get them in your .cs file? answer is, use "ConfigurationSettings" class under system. so if you want to the value "source" in .cs just type in this
string k = ConfigurationSettings.AppSettings["Source"].ToString();
but as soon as you type that in, if you are using .net 4.0 you are going to encounter the second problem. the line will be underlined in green which will say some thing like,
System.Configuration.ConfigurationSettings.AppSettings’ is obsolete: ‘This method is obsolete, it has been replaced by System.Configuration!System.Configuration.ConfigurationManager.AppSettings
so then you will likely be using "ConfigurationManager" instead. now you face the third problem. it will say, "ConfigurationManager does not exists in current context" [i do not have clue why this sentence cannot be some thing like this "We cannot find the damn thing. check your references"]
Since "ConfigurationSettings" came under intelli-sense without referencing anything, logical deduction was i will see "ConfigurationManager" in the same list since both of them belong to System.Configuration. i googled it a lot and found out that you have to manually reference System.ConfigurationManager into the application. "why on earth you have to do this for Manager and do not have to do it for settings" is something i yet to discover.
So once you reference "System.ConfigurationManager" all will become cake walk to you. and the final code for getting the value of "Source" will be,
source = ConfigurationManager.AppSettings["Source"].ToString();

When you laugh at the irony...sometime it turns around and laughs at you....

ok here's the thing...i have moved back to dynamics CRM again....the reason, i got a new job which deals with CRM development, the version of course is 2011. it gives me great pleasure to find out dynamics CRM has not been changed much from what it used to be two lives back. it still remains baffling and there are not much code example on the net. having said that, MSDN - CRM Community remains the great saviour for a novice programmer like me.
enough said. i don't want to provide a full proof article about my ignorance on CRM or any techs for that matter. i have done so many things on .NET lately. I'm sure if I don't safe keep the codings that i have done so far, they will soon be perished in the hard drive and i won't be finding them just when i need them.
so here's the plan. for the next few posts i will be providing some .net code which i have used over and over again. I will be spicing the posts with some small code snippets/thoughts/curses on dynamics CRM from my "novice point of view".
advisory statement: the codes may not seem very intriguing for all you smart asses. but these codes saved my life many a occasions. and obviously this is my post and i am writing it.