protected Entity CreateAccount() { var entity = new Entity(Entities.account); var maxNameLength = XrmService.GetMaxLength(Fields.account_.name, Entities.account); entity.SetField(Fields.account_.name, "Test Account - " + DateTime.Now.ToLocalTime()); entity.SetField(Fields.account_.fax, "0999999999fax"); entity.SetField(Fields.account_.telephone1, "0999999999"); entity.SetField(Fields.account_.emailaddress1, "*****@*****.**"); entity.SetField(Fields.account_.address1_line1, "100 Collins St"); entity.SetField(Fields.account_.address1_city, "Melbourne"); entity.SetField(Fields.account_.address1_stateorprovince, "VIC"); entity.SetField(Fields.account_.address1_postalcode, "3000"); Entity contact = CreateContact(null); entity.SetLookupField(Fields.account_.primarycontactid, contact); var account = CreateAndRetrieve(entity); contact.SetLookupField(Fields.contact_.parentcustomerid, account); XrmService.Update(contact, new[] { Fields.contact_.parentcustomerid }); return(account); }
/// <summary> /// Returns list of key values giving the types and field name parsed for the given string of field joins /// key = type, value = field /// </summary> /// <param name="xrmService"></param> /// <param name="fieldPath"></param> /// <param name="sourceType"></param> /// <returns></returns> public static IEnumerable <KeyValuePair <string, string> > GetTypeFieldPath(this XrmService xrmService, string fieldPath, string sourceType) { var list = new List <KeyValuePair <string, string> >(); var splitOutFunction = fieldPath.Split(':'); if (splitOutFunction.Count() > 1) { fieldPath = splitOutFunction.ElementAt(1); } var split = fieldPath.Split('.'); var currentType = sourceType; list.Add(new KeyValuePair <string, string>(currentType, split.ElementAt(0).Split('|').First())); var i = 1; if (split.Length > 1) { foreach (var item in split.Skip(1).Take(split.Length - 1)) { var fieldName = item.Split('|').First(); if (split.ElementAt(i - 1).Contains("|")) { var targetType = split.ElementAt(i - 1).Split('|').Last(); list.Add(new KeyValuePair <string, string>(targetType, fieldName)); currentType = targetType; } else { var targetType = xrmService.GetLookupTargetEntity(list.ElementAt(i - 1).Value, currentType); list.Add(new KeyValuePair <string, string>(targetType, fieldName)); currentType = targetType; } i++; } } return(list); }
public virtual Entity CreateAndRetrieve(Entity entity, XrmService xrmService = null) { if (xrmService == null) { xrmService = XrmService; } var primaryField = xrmService.GetPrimaryField(entity.LogicalName); if (!entity.Contains(primaryField)) { entity.SetField(primaryField, ("Test Scripted Record" + DateTime.UtcNow.ToFileTime()).Left(xrmService.GetMaxLength(primaryField, entity.LogicalName))); } if (entity.LogicalName == Entities.contact && !entity.Contains(Fields.contact_.firstname)) { entity.SetField(Fields.contact_.firstname, "Test"); } if (entity.LogicalName == Entities.lead && !entity.Contains(Fields.lead_.firstname)) { entity.SetField(Fields.lead_.firstname, "Test"); } var id = xrmService.Create(entity); return(xrmService.Retrieve(entity.LogicalName, id)); }
public string GetOptionLabel(int value, string field) { return(XrmService.GetOptionLabel(value, field, TargetType)); }
public string GetEntityLabel() { return(XrmService.GetEntityDisplayName(TargetType)); }
public string GetEntityCollectionLabel() { return(XrmService.GetEntityCollectionName(TargetType)); }
public $ext_jmobjprefix$RollupService(XrmService xrmService) : base(xrmService)
public string GetFieldLabel(string fieldName) { return(XrmService.GetFieldLabel(fieldName, TargetType)); }
public static string GenerateEmailContent(this XrmService xrmService, string emailTemplateResourceName, string emailTemplateTargetType, Guid emailTemplateTargetId, string crmurl = null, string appendAppIdToCrmUrl = null) { string activityDescription = null; var targetTokens = new List <string>(); var staticTokens = new Dictionary <string, List <string> >(); var ifTokens = new List <string>(); var staticIdentifier = "STATIC|"; var ifIdentifier = "IF|"; var endifIdentifier = "ENDIF"; if (emailTemplateResourceName != null) { var resource = xrmService.GetFirst(Entities.webresource, Fields.webresource_.name, emailTemplateResourceName); if (resource == null) { throw new NullReferenceException(string.Format("Could Not Find {0} With {1} '{2}'", xrmService.GetEntityLabel(Entities.webresource), xrmService.GetFieldLabel(Fields.webresource_.name, Entities.webresource), emailTemplateResourceName)); } var encoded = resource.GetStringField(Fields.webresource_.content); byte[] binary = Convert.FromBase64String(encoded); activityDescription = UnicodeEncoding.UTF8.GetString(binary); if (appendAppIdToCrmUrl != null) { var baseUrlPart = "crminstanceurl]/main.aspx?"; activityDescription = activityDescription.Replace(baseUrlPart, baseUrlPart + "appid=" + appendAppIdToCrmUrl + "&"); } //parse out all tokens inside [] chars to replace in the email var i = 0; while (i < activityDescription.Length) { if (activityDescription[i] == '[') { var startIndex = i; while (i < activityDescription.Length) { if (activityDescription[i] == ']') { var endIndex = i; var token = activityDescription.Substring(startIndex + 1, endIndex - startIndex - 1); if (token.ToUpper().StartsWith(ifIdentifier) || token.ToUpper().StartsWith(endifIdentifier)) { ifTokens.Add(token); } else if (token.ToUpper().StartsWith(staticIdentifier)) { token = token.Substring(staticIdentifier.Length); var split = token.Split('.'); if (split.Count() != 2) { throw new Exception(string.Format("The static token {0} is not formatted as expected. It should be of the form type.field", token)); } var staticType = split.First(); var staticField = split.ElementAt(1); if (!staticTokens.ContainsKey(staticType)) { staticTokens.Add(staticType, new List <string>()); } staticTokens[staticType].Add(staticField); } else { targetTokens.Add(token); } break; } i++; } } else { i++; } } } //query to get all the fields for replacing tokens var query = xrmService.BuildSourceQuery(emailTemplateTargetType, targetTokens); query.Criteria.AddCondition(new ConditionExpression(xrmService.GetPrimaryKeyField(emailTemplateTargetType), ConditionOperator.Equal, emailTemplateTargetId)); var targetObject = xrmService.RetrieveFirst(query); //process all the ifs (clear where not) while (ifTokens.Any()) { var endIfTokenStackCount = 0; var removeAll = false; var token = ifTokens.First(); if (token.ToUpper() != endifIdentifier) { var tokenIndex = activityDescription.IndexOf(token); var indexOf = token.IndexOf("|"); if (indexOf > -1) { var field = token.Substring(indexOf + 1); var fieldValue = targetObject.GetFieldValue(field); var endIfTokenStack = 1; var remainingTokens = ifTokens.Skip(1).ToList(); while (true && remainingTokens.Any()) { if (remainingTokens.First().ToUpper() == endifIdentifier) { endIfTokenStack--; endIfTokenStackCount++; } else { endIfTokenStack++; } remainingTokens.RemoveAt(0); if (endIfTokenStack == 0) { break; } } //okay so starting at the current index need to find the end if //and remove the content or the tokens var currentStack = endIfTokenStackCount; var currentIndex = activityDescription.IndexOf(token); while (currentStack > 0) { var endIfIndex = activityDescription.IndexOf(endifIdentifier, currentIndex, StringComparison.OrdinalIgnoreCase); if (endIfIndex > -1) { currentIndex = endIfIndex; currentStack--; } else { break; } } removeAll = fieldValue == null; if (removeAll) { var startRemove = tokenIndex - 1; var endRemove = currentIndex + endifIdentifier.Length + 1; activityDescription = activityDescription.Substring(0, startRemove) + activityDescription.Substring(endRemove); } else { var startRemove = tokenIndex - 1; var endRemove = currentIndex - 1; activityDescription = activityDescription.Substring(0, startRemove) + activityDescription.Substring(startRemove + token.Length + 2, endRemove - startRemove - token.Length - 2) + activityDescription.Substring(endRemove + endifIdentifier.Length + 2); } } } ifTokens.RemoveRange(0, endIfTokenStackCount > 0 ? endIfTokenStackCount * 2 : 1); } //replace all the tokens foreach (var token in targetTokens) { var sourceType = emailTemplateTargetType; string displayString = xrmService.GetDisplayString(targetObject, token, isHtml: true); activityDescription = activityDescription.Replace("[" + token + "]", displayString); } foreach (var staticTargetTokens in staticTokens) { var staticType = staticTargetTokens.Key; var staticFields = staticTargetTokens.Value; //query to get all the fields for replacing tokens var staticQuery = xrmService.BuildSourceQuery(staticType, staticFields); var staticTarget = xrmService.RetrieveFirst(staticQuery); //replace all the tokens foreach (var staticField in staticFields) { string staticFunc = null; activityDescription = activityDescription.Replace("[STATIC|" + string.Format("{0}.{1}", staticType, staticField) + "]", xrmService.GetFieldAsDisplayString(staticType, staticField, staticTarget.GetFieldValue(staticField), isHtml: true, func: staticFunc)); } } return(activityDescription); }
public object GetAggregate(Guid id, XrmService service) { object newValue = null; switch (AggregateType) { case AggregateType.Exists: { //if the aggregate returns a result > 0 then one exists var fetch = GetLookupFetch(id); var result = service.RetrieveAllFetch(fetch); newValue = result.Any() && XrmEntity.GetInt(result.ElementAt(0).GetFieldValue(FetchAlias)) > 0; break; } case AggregateType.Count: { var result = service.RetrieveAllFetch(GetLookupFetch(id)); if (result.Any()) { newValue = result.ElementAt(0).GetFieldValue(FetchAlias); } break; } case AggregateType.Sum: { var result = service.RetrieveAllFetch(GetLookupFetch(id)); if (result.Any()) { newValue = result.ElementAt(0).GetFieldValue(FetchAlias); } break; } case AggregateType.Min: { var query = GetAggregatedRecordQueryForLookup(id); query.AddOrder(AggregatedField, OrderType.Ascending); var minRecord = service.RetrieveFirst(query); newValue = minRecord.GetField(AggregatedField); break; } case AggregateType.CSV: case AggregateType.PSV: { var query = GetAggregatedRecordQueryForLookup(id); query.AddOrder(AggregatedField, OrderType.Ascending); var records = service.RetrieveAll(query); var labels = records.Select( delegate(Entity item) { return(item.GetField(AggregatedField)); }). ToArray(); if (AggregateType == AggregateType.CSV) { newValue = string.Join(", ", labels); } else { newValue = string.Join("|", labels); } newValue = ((string)newValue).Left(1000); break; } } if (newValue == null && NullAmount != null) { newValue = NullAmount; } return(newValue); }
protected XrmTest() { Controller = new LogController(); XrmServiceAdmin = new XrmService(XrmConfiguration, Controller); }
public IEnumerable <Entity> GetRegardingNotes(Entity regardingObject) { return(XrmService.RetrieveAllAndClauses("annotation", new[] { new ConditionExpression("objectid", ConditionOperator.Equal, regardingObject.Id) }, null)); }
public OrganisationSettings(XrmService xrmService) { XrmService = xrmService; }
public Entity UpdateFieldsAndRetreive(Entity entity, IEnumerable <string> fieldsToUpdate) { XrmService.Update(entity, fieldsToUpdate); return(XrmService.Retrieve(entity.LogicalName, entity.Id)); }
public virtual Entity UpdateFieldsAndRetreive(Entity entity, params string[] fieldsToUpdate) { return(XrmService.UpdateAndRetrieve(entity, fieldsToUpdate)); }
protected XrmTest() { Controller = new LogController(); Controller.AddUi(new DebugUserInterface()); XrmServiceAdmin = new XrmService(XrmConfigurationAdmin, Controller); }
public Entity Refresh(Entity entity) { return(XrmService.Retrieve(entity.LogicalName, entity.Id)); }
public void Debug() { var me = XrmService.WhoAmI(); }
public $ext_jmobjprefix$SharepointService(XrmService xrmService, ISharePointSettings sharepointSettings) : base(sharepointSettings, xrmService)
public Entity Refresh(Entity entity) { return(XrmService.Refresh(entity)); }
/// <summary> /// Parses and sets the field in the entity /// </summary> public static void SetField(this Entity entity, string fieldName, object value, XrmService service) { entity[fieldName] = service.ParseField(fieldName, entity.LogicalName, value); }
public Entity CreateTestRecord(string entityType, Dictionary <string, object> fields, XrmService xrmService = null) { var entity = new Entity(entityType); foreach (var field in fields) { entity.SetField(field.Key, field.Value); } return(CreateAndRetrieve(entity, xrmService)); }
public $ext_jmobjprefix$Settings(XrmService xrmService) { XrmService = xrmService; }
public void PopulateField(string field, Entity entity) { var type = entity.LogicalName; var fieldType = XrmService.GetFieldType(field, type); switch (fieldType) { case AttributeTypeCode.BigInt: { entity.SetField(field, 1); break; } case AttributeTypeCode.Boolean: { entity.SetField(field, true); break; } case AttributeTypeCode.CalendarRules: { break; } case AttributeTypeCode.Customer: { entity.SetField(field, CreateAccount()); break; } case AttributeTypeCode.DateTime: { var now = DateTime.UtcNow; var noMilliSeconds = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, DateTimeKind.Utc); entity.SetField(field, noMilliSeconds); break; } case AttributeTypeCode.Decimal: { entity.SetField(field, (decimal)1); break; } case AttributeTypeCode.Double: { entity.SetField(field, (double)1); break; } case AttributeTypeCode.EntityName: { break; } case AttributeTypeCode.Integer: { entity.SetField(field, 1); break; } case AttributeTypeCode.Lookup: { var target = XrmService.GetLookupTargetEntity(field, type); var typesToExlcude = new[] { "equipment", "transactioncurrency", "pricelevel", "service", "systemuser", "incident", "campaign", "territory" }; if (!typesToExlcude.Contains(target)) { entity.SetField(field, CreateTestRecord(target).ToEntityReference()); } break; } case AttributeTypeCode.ManagedProperty: { break; } case AttributeTypeCode.Memo: { entity.SetField(field, "blah blah blah \n blah"); break; } case AttributeTypeCode.Money: { entity.SetField(field, new Money(1)); break; } case AttributeTypeCode.Owner: { entity.SetField(field, new EntityReference("systemuser", CurrentUserId)); break; } case AttributeTypeCode.PartyList: { entity.AddActivityParty(field, "systemuser", CurrentUserId); break; } case AttributeTypeCode.Picklist: { entity.SetField(field, new OptionSetValue(XrmService.GetOptions(field, type).First().Key)); break; } case AttributeTypeCode.State: { break; } case AttributeTypeCode.Status: { break; } case AttributeTypeCode.String: { entity.SetField(field, "1234"); break; } case AttributeTypeCode.Uniqueidentifier: { break; } case AttributeTypeCode.Virtual: { break; } } }
public void RefreshRollup(Guid id, LookupRollup rollup) { var newValue = GetRollup(rollup, id); XrmService.SetFieldIfChanging(rollup.RecordTypeWithRollup, id, rollup.RollupField, newValue); }
public RollupService(XrmService xrmService) { XrmService = xrmService; }
public object GetRollup(LookupRollup rollup, Guid id) { object newValue = null; switch (rollup.RollupType) { case RollupType.Exists: { //if the Rollup returns a result > 0 then one exists var fetch = GetLookupFetch(rollup, id); var result = XrmService.Fetch(fetch); newValue = result.Any() && XrmEntity.GetInt(result.First().GetFieldValue(FetchAlias)) > 0; break; } case RollupType.Count: { var result = XrmService.Fetch(GetLookupFetch(rollup, id)); if (result.Any()) { newValue = result.ElementAt(0).GetFieldValue(FetchAlias); } break; } case RollupType.Sum: { var result = XrmService.Fetch(GetLookupFetch(rollup, id)); if (result.Any()) { newValue = result.ElementAt(0).GetFieldValue(FetchAlias); } break; } case RollupType.Min: { var query = GetRollupQueryForLookup(rollup, id); query.AddOrder(rollup.FieldRolledup, OrderType.Ascending); var minRecord = XrmService.RetrieveFirst(query); newValue = minRecord.GetField(rollup.FieldRolledup); break; } case RollupType.CSV: case RollupType.PSV: { var query = GetRollupQueryForLookup(rollup, id); query.AddOrder(rollup.FieldRolledup, OrderType.Ascending); var records = XrmService.RetrieveAll(query); var labels = records.Select(e => e.GetField(rollup.FieldRolledup)). ToArray(); if (rollup.RollupType == RollupType.CSV) { newValue = string.Join(", ", labels); } else { newValue = string.Join("|", labels); } newValue = ((string)newValue).Left(1000); break; } } if (newValue == null && rollup.NullAmount != null) { newValue = rollup.NullAmount; } if (newValue != null && rollup.ObjectType != null) { if (rollup.ObjectType == typeof(decimal)) { newValue = Convert.ToDecimal(newValue.ToString()); } } return(newValue); }
/// <summary> /// Basic script for verifying configured Rollups - not only uses active filter in scenarios /// </summary> /// <summary> /// Basic script for verifying configured Rollups - not only uses active filter in scenarios /// </summary> public void VerifyRollupScenarios(string parentType, string childType, string referenceField) { var Rollups = $ext_jmobjprefix$RollupService .GetRollupsForRolledupType(childType) .Where(a => a.RecordTypeWithRollup == parentType) .ToArray(); var contactFieldsRollupd = Rollups.Select(a => a.FieldRolledup).ToArray(); var parent1 = CreateTestRecord(parentType); foreach (var rollup in Rollups) { if (rollup.NullAmount != null) { Assert.IsTrue(XrmEntity.FieldsEqual(rollup.NullAmount, parent1.GetField(rollup.RollupField))); } } var parent2 = CreateTestRecord(parentType); //create new child linked to parent and verify the rollup fields populated var child1 = new Entity(childType); PopulateRollupFields(child1); child1.SetLookupField(referenceField, parent1); child1 = CreateAndRetrieve(child1); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsNotNull(child1.GetField(rollup.FieldRolledup)); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //create second child linked to parent and verify the rollup fields added var child2 = new Entity(childType); PopulateRollupFields(child2); child2.SetLookupField(referenceField, parent1); child2 = CreateAndRetrieve(child2); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { Assert.IsNotNull(child1.GetField(rollup.FieldRolledup)); Assert.IsNotNull(child2.GetField(rollup.FieldRolledup)); var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //change second child to second parent and verify both parents updated child2.SetLookupField(referenceField, parent2); child2 = UpdateFieldsAndRetreive(child2, referenceField); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { Assert.IsNotNull(child1.GetField(rollup.FieldRolledup)); var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } parent2 = Refresh(parent2); foreach (var rollup in Rollups) { Assert.IsNotNull(child2.GetField(rollup.FieldRolledup)); var expectedValue2 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue2, parent2.GetField(rollup.RollupField))); } //triple each value in child 1 and verify updated in parent PopulateRollupFields(child1, multiplier: 3); child1 = UpdateFieldsAndRetreive(child1, contactFieldsRollupd); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { Assert.IsNotNull(child1.GetField(rollup.FieldRolledup)); var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //negate value in child 1 and verify updated in parent PopulateRollupFields(child1, multiplier: 2); child1 = UpdateFieldsAndRetreive(child1, contactFieldsRollupd); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { Assert.IsNotNull(child1.GetField(rollup.FieldRolledup)); var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //create child in account 1 and verify updated var child3 = new Entity(childType); PopulateRollupFields(child3); child3.SetLookupField(referenceField, parent1); child3 = CreateAndRetrieve(child3); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { Assert.IsNotNull(child3.GetField(rollup.FieldRolledup)); var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //deactivate and verify updated XrmService.SetState(child3.LogicalName, child3.Id, 1); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //activate and verify updated XrmService.SetState(child3.LogicalName, child3.Id, 0); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //delete and verify updated Delete(child3); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { Assert.IsNotNull(child1.GetField(rollup.FieldRolledup)); var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //lets create one without the fields populated just to verify no error child3 = new Entity(childType); child3.SetLookupField(referenceField, parent1); child3 = CreateAndRetrieve(child3); parent1 = Refresh(parent1); foreach (var rollup in Rollups) { var expectedValue1 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent1.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue1, parent1.GetField(rollup.RollupField))); } //same activate / deactivate / delete for the parent 2 //this includes changing to not exists //deactivate and verify updated XrmService.SetState(child2.LogicalName, child2.Id, 1); parent2 = Refresh(parent2); foreach (var rollup in Rollups) { var expectedValue2 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent2.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue2, parent2.GetField(rollup.RollupField))); } //activate and verify updated XrmService.SetState(child2.LogicalName, child2.Id, 0); parent2 = Refresh(parent2); foreach (var rollup in Rollups) { var expectedValue2 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent2.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue2, parent2.GetField(rollup.RollupField))); } //delete and verify updated Delete(child2); parent2 = Refresh(parent2); foreach (var rollup in Rollups) { var expectedValue2 = $ext_jmobjprefix$RollupService.GetRollup(rollup, parent2.Id); Assert.IsTrue(XrmEntity.FieldsEqual(expectedValue2, parent2.GetField(rollup.RollupField))); } DeleteMyToday(); }
private void AppendThForField(StringBuilder table, Microsoft.Xrm.Sdk.Entity firstItem, string field) { var path = XrmService.GetTypeFieldPath(field, firstItem.LogicalName); table.AppendLine(string.Format("<th {0}>{1}</th>", thStyle, XrmService.GetFieldLabel(path.Last().Value, path.Last().Key))); }