This callout calculates how much time has been spent on activities within an incident.
First thing I did was customise the incident entity to include an incident total time field which I made read only to protect the data.
Now all we need is a callout to total up the total time of the incidents.
I based this callout on incident resolution and created the following code.
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Xml;
using System.IO;
using System.Security.Principal;
using Microsoft.Crm.Callout;
using Microsoft.Win32;
namespace DotNetDeveloper.Callout
{
/// <summary>
/// Summary description for CaseResolutionCallout.
/// </summary>
public class CaseResolutionCallout : CrmCalloutBase
{
#region constructors
/// <summary>
/// empty constructor
/// </summary>
public CaseResolutionCallout()
{}
#endregion
#region Public Methods
/// <summary>
/// PreCalloutReturnValue
/// </summary>
/// <param name="userContext"></param>
/// <param name="entityContext"></param>
/// <param name="newStateCode"></param>
/// <param name="newStatusCode"></param>
/// <param name="errorMessage"></param>
/// <returns></returns>
public override PreCalloutReturnValue PreSetState(CalloutUserContext userContext, CalloutEntityContext entityContext, ref int newStateCode, ref int newStatusCode, ref string errorMessage)
{
// only do this for Incident resolution
if (newStateCode == 1)
{
try
{
// setup impersonation
using (CrmService service = new CrmService())
{
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
service.CallerIdValue = new CallerId();
service.CallerIdValue.CallerGuid = userContext.UserId;
// get total time spent on case
CalculateTotalTimeIncidentRequest req = new CalculateTotalTimeIncidentRequest();
req.IncidentId = new System.Guid(entityContext.InstanceId.ToString());
CalculateTotalTimeIncidentResponse resp = (CalculateTotalTimeIncidentResponse)service.Execute(req);
// update the case
incident inc = new incident();
inc.incidentid = new Key();
inc.incidentid.Value = new Guid(entityContext.InstanceId.ToString());
inc. totalincidenttime = resp.TotalTime.ToString();
service.Update(inc);
}
}
catch (Exception ex)
{
// error handling code
}
}
return PreCalloutReturnValue.Continue;
}
#endregion
}
}
Obviously you need to add a reference to the base callout class and also to the MSCRM Service.
Associated Callout.Config.xml code
<callout entity="incident" event="PreSetState">
<subscription assembly="DotNetDeveloper.Callout.dll" class="DotNetDeveloper.Callout.CaseResolutionCallout"></subscription>
</callout>
Ok that done, upon running this callout you will find that the callout should works as expected and populate the totalincidenttime.
One activity I would test more than others would be the appointment activity, as the method provided by Microsoft calculates the incorrect totaltime for appointments ( I came across the problem and solution and posted about it in this earlier post here .