If you just need the fields calculated for display purposes you could do something like this
- Create your new fields
- Register a new plugin on Post Retrieve and RetrieveMultiple of Project entity
- Copy the logic from the code below, swapping entity/field names where needed.
What my code is doing is intercepting Contact records whenever they're to be displayed in CRM. This means in grids, forms, dashboards etc. It'll then calculate the time difference on the spot and populate the fields with the result. By then populating the entity object in the OutputParameters, the front end receives those values and can display them where appropriate.
The only downside here is that because those fields are calculated directly in CRM you won't be able to write any SSRS reports as the data isn't persisted to the database. If you were to implement this and then go do a SQL query against those fields you'll find them all null. Those fields merely act as placeholders. (see screenshots)
protected void ExecutePreValidateContactRetrieve(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
IPluginExecutionContext pluginContext = localContext.PluginExecutionContext;
if (pluginContext.OutputParameters.Contains("BusinessEntity"))
{
Entity target = (Entity)pluginContext.OutputParameters["BusinessEntity"];
PopulateKPIs(localContext.OrganizationService, target);
}
else if (pluginContext.OutputParameters.Contains("BusinessEntityCollection"))
{
EntityCollection contacts = (EntityCollection)localContext.PluginExecutionContext.OutputParameters["BusinessEntityCollection"];
foreach (Entity c in contacts.Entities)
PopulateKPIs(localContext.OrganizationService, c);
}
}
public void PopulateKPIs(IOrganizationService orgService, Entity contact)
{
DateTime createdOn;
if (!contact.Contains("createdon"))
createdOn = orgService.Retrieve(contact.LogicalName, contact.Id, new ColumnSet("createdon")).GetAttributeValue<DateTime>("createdon");
else
createdOn = contact.GetAttributeValue<DateTime>("createdon");
TimeSpan diff = DateTime.Now - createdOn;
contact["mst_secondssincecreation"] = Math.Floor(diff.TotalSeconds).ToString();
contact["mst_minutessincecreation"] = Math.Floor(diff.TotalMinutes).ToString();
contact["mst_hourssincecreation"] = Math.Floor(diff.TotalHours).ToString();
}
Evidence: