Tuesday, 19 February 2013

CRM 2011 - How do you close an opportunity in Silverlight?

This is an interesting one I came across today. Due to using a different set of objects within the Silverlight framework you'll notice you're missing that valuable "WinOpportunityRequest" object! So, it begs the question, how do you close an opportunity in Silverlight?

Thankfully, we can go back to basics and raise an ordinary OrganizationRequest to achieve this. But before we do this let's take a look at what the code might look like in a plugin or standard CRM service request:

var opportunityClose = new Entity("opportunityclose");
    new EntityReference("opportunity", opportunityId));
opportunityClose.Attributes.Add("subject", "Opportunity expired");

var winOpportunity = new WinOpportunityRequest
        OpportunityClose = opportunityClose,
        Status = new OptionSetValue(20001) // or whatever is valid for you

You might be tempted to try achieve this using a SetState request, but you'll quickly find CRM complaining and telling you you're not allowed to do it. Instead, an easier way to do this is just replicate the above call as if you were using late binding. Like this:

var organizationRequest = new OrganizationRequest
   { RequestName = (won ? "WinOpportunity" : "LoseOpportunity") };
var opportunityClose = new Entity {LogicalName = "opportunityclose"};
SetAttribute(opportunityClose, "opportunityid", opportunityEntity.Id);
SetAttribute(opportunityClose, "subject", "Opportunity Expired");
organizationRequest["OpportunityClose"] = opportunityClose;
organizationRequest["Status"] = new OptionSetValue {Value = 20001}; // or whatever is valid for you

For reference, my SetAttribute function just looks like this:

private void SetAttribute(Entity entity, string attribute, object value)
  if (entity != null)
    if (entity.Attributes == null) entity.Attributes = new AttributeCollection();
    if (entity.Attributes.ContainsKey(attribute))
       entity.Attributes.SetItem(attribute, value);
          new Common.XrmSoapService.KeyValuePair<string, object> 
             { Key = attribute, Value = value });