dynamics crm plugin error - c#

I have an issue with my plugin, I have a custom entity new_smsmessage and from my plugin I want to retrieve custom attributes to send text message, but it gives me the following error message "The given key was not present in the dictionary". The plugin's code is shown bellow and the names of attributes are correct in the CRM entity:
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
Entity entity = (Entity)context.InputParameters["target"];
string uservalue = "";
string phonevalue = "";
string aliasevalue = "";
ColumnSet columnSet = new ColumnSet(true);
ColumnSet allFields = new ColumnSet() { AllColumns = true };
ExternalSMSService1.ExternalSMSService wbSrvSMS = new ExternalSMSService1.ExternalSMSService();
string strToken = wbSrvSMS.Login(userName, pwd);
string smsResult = string.Empty;
if (entity.Attributes.Contains("new_username"))
{
uservalue = entity.Attributes["new_username"].ToString();
}
else
{
throw new InvalidPluginExecutionException("field name not found");
}
if (entity.Attributes.Contains("new_userphone"))
{
phonevalue = entity.Attributes["new_userphone"].ToString();
}
else
{
throw new InvalidPluginExecutionException("field Phone not found");
}
if (entity.Attributes.Contains("new_aliasecode"))
{
phonevalue = entity.Attributes["new_aliasecode"].ToString();
}
else
{
throw new InvalidPluginExecutionException("aliase Phone not found");
}
string smsmessage = entity.Attributes["new_message"].ToString();
string[] strArr = null;
string[] strArr2;
char[] splitchar = { ';' };
strArr = uservalue.Split(splitchar);
char[] splitchar2 = { '-' };
strArr2 = phonevalue.Split(splitchar2);
for (int i = 0; i < strArr.Length; i++)
{
StringBuilder strMsg = new StringBuilder();
strMsg.Append("<SEND_SMS>");
strMsg.Append("<MSG_DATA TEXT='" + smsmessage + "' SHORT_CODE='" + aliasevalue + "'/>");
strMsg.Append("<RECIPIENTS>");
strMsg.Append("<RECIPIENT MOBILE_NUMBER='" + strArr2[i].ToString() + "' RECP_NAME ='" + strArr[i].ToString() + "'/>");
strMsg.Append("</RECIPIENTS>");
strMsg.Append("</SEND_SMS>");
smsResult = wbSrvSMS.SendSMS(strMsg.ToString(), strToken);
}
}

Try to change line
Entity entity = (Entity)context.InputParameters["target"];
to
Entity entity = (Entity)context.InputParameters["Target"];

It's ok now, i've just forgot to modify my variable
Thanks

Always first check key before getting like.
if (_entity.Attributes.ContainsKey("field1"))
{Here code to get field1 value }
Because return entity not contains attributes having null values.

Related

C# Linq with four tables and one foreign key that isn´t always needed

I have the problem that I have a MariaDB database with HeidiSQL. There are four tables and im using Linq to insert new data. One of the tables isn´t always necessary. So i marked the column with the foreign key in one of the a other tables for can be NULL. The problem is that when i create the new objects to insert into database it creates the new data in the database but the foreign key in the other table keeps emtpy.
When i undo the Null option in the column and want to insert a standardvalue instead, it throws an UpdateEntityException.
What i should mention is, that i cerated the database first in HeidiSQL and created then the code in Visual Studio with EntityFramework 5.0.
Or might the mistake caused by building and adding the database object in an if-clause?
There are some code examples of my code, i hope it will help.
DateTime aktuellesDatum = DateTime.Now;
int proId = getProjectIdByProjectnumber(zeichnungen[0].Projektnummer);
int tagId = getTagIdByTag(zeichnungen[0].Tag, zeichnungen[0].Projektnummer);
string hauptzeichnung = "";
int gruppeId = -1;
//Noch kein Projekt vorhanden
if(proId == -1)
{
using (DMSContext db = new DMSContext())
{
foreach (ZeichnungInDB zeichnungInDB in zeichnungen)
{
zeichnungInDB.Volante_Index = getVolCountByDrawingNumber(zeichnungInDB.Zeichnungsnummer) + 1;
var zeichnung = new zeichnung()
{
Zeichnung_ID = zeichnungInDB.Dateiname + "_" + zeichnungInDB.Index + "_VOL_" + zeichnungInDB.Volante_Index + "_" + aktuellesDatum.ToShortDateString(),
Zeichnungsnummer = zeichnungInDB.Zeichnungsnummer,
Index = zeichnungInDB.Index,
Zeitstempel = aktuellesDatum,
Dateiname_Org = zeichnungInDB.Dateiname,
Aenderung_Ext = zeichnungInDB.Aenderung_Ext,
Aenderung_Int = "AE_" + zeichnungInDB.Projektnummer + "_" + aktuellesDatum.Year + "-" + aktuellesDatum.Month + "-" + aktuellesDatum.Day + " " + aktuellesDatum.Hour + ":" + aktuellesDatum.Minute,
Dokumententyp = zeichnungInDB.DokumentenTyp,
Dateiendung = zeichnungInDB.Extension,
Volante_Index = zeichnungInDB.Volante_Index,
MMS_Sachmerkmal = zeichnungInDB.Mms_Sachmerkmal,
Status = zeichnungInDB.Status,
Aenderung_Bemerkung_Txt = zeichnungInDB.Aenderung_Bemerkung_Text,
Einzel_Bemerkung_Txt = zeichnungInDB.Einzel_Bemerkung,
Ahang_Link = zeichnungInDB.Anhang_Link,
Einzel_Link = zeichnungInDB.Einzel_Link,
};
db.zeichnungs.Add(zeichnung);
if(zeichnungInDB.Baugruppe_Hauptzeichnung == true)
{
hauptzeichnung = zeichnungInDB.Zeichnungsnummer;
}
}
var projekt = new projekt()
{
Projektnummer = zeichnungen[0].Projektnummer,
};
var tag = new tag()
{
Tag1 = zeichnungen[0].Tag,
};
if (!hauptzeichnung.Equals(""))
{
var baugruppe = new baugruppe
{
Hauptzeichnung = hauptzeichnung,
};
db.baugruppes.Add(baugruppe);
}
db.projekts.Add(projekt);
db.tags.Add(tag);
try
{
db.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
}
This is only a short e.g. from my code because the whole cs would be to long and nobody would spend the time on so much code.
One other thing i would like to ask is. If the following code works correct for update a string in a field?
private static void updateHauptzeichnung(int baugruppeId, string zeichnungsnummer)
{
using (var context = new DMSContext())
{
var query = context.baugruppes
.Where(b => b.Baugruppe_ID == baugruppeId)
.Select(g => new { g.Hauptzeichnung })
.SingleOrDefault();
if (query != null)
{
query.Hauptzeichnung.Replace(query.Hauptzeichnung, zeichnungsnummer);
}
context.SaveChanges();
}
}
I solved my problem. I changed the foreignkey field from can be NULL to is necessary, added in the foreign table a costum dataset with ID is 0 and I give new data this ID as its foreign ID when they have no offical link to the foreign table. It might not be the best solution, but it fixed my problem.

foreach loop is not working in mvc

foreach (int workFlowServiceDetail in workFlowServiceDetails)
{
using (var db = new AdminDb())
{
string workFlowServiceDtl = (from perm in db.WorkFlowPermission.AsNoTracking()
where perm.WorkFlowPermissionId == workFlowServiceDetail
select perm.Service).FirstOrDefault();
//to select eligibility rules against this service
string eligibility = (from definition in db.WorkFlowDefinition.AsNoTracking()
join model in db.WorkFlowModel.AsNoTracking()
on definition.WorkFlowDefinitionId equals model.WorkFlowDefinitionId
join permission in db.WorkFlowPermission.AsNoTracking()
on model.WorkFlowDefinitionId equals permission.WorkFlowDefinitionId
where model.ControllerNameId.Equals(current_ControllerId) && permission.WorkFlowPermissionId == workFlowServiceDetail
select permission.EligibilityRule).FirstOrDefault();
if (eligibility == null)
{
string validationMessage = "";
validationMessage = "Please set eligibility for workflow permission";
serviceName = null;
permissionId = 0;
return new CustomBusinessServices() { strMessage = validationMessage };
}
string[] strTxt = workFlowServiceDtl.Split(';'); //split the service name by ';' and strore it in an array
string serviceUrl = string.Empty;
string workFlowServiceName = string.Empty;
string classpath = string.Empty;
workFlowServiceName = strTxt[0].ToString();
workFlowServiceName = workFlowServiceName.Replace(" ", "");//get the service name by removing empty blank space for the word
classpath = strTxt[1].ToString();
//Invoke REST based service (like Node.Js service)
if (strTxt.Length == 4)
{
serviceUrl = strTxt[3].ToString();
}
//Invoke c# based service
else
{
serviceUrl = string.Empty;
}
var userLists = PermissionCallMethod(classpath, workFlowServiceName, new[] { workFlowImplemented, eligibility }, serviceUrl);
/*****************************************Problem in this loop**********/
if (userLists.UserList.Contains(userId))
{
serviceName = strTxt[0].ToString() + ";Aspir.Pan.Common.WorkFlowNotificationServices;" + strTxt[2].ToString();
permissionId = workFlowServiceDetail;
return userLists;
}
}
}
serviceName = string.Empty;
permissionId = 0;
return null;
Inside this loop a condition is checked to find a particular user form alist of user.Once the condition is true it jump out of the loop without checking the next one.
if (userLists.UserList.Contains(userId))
{
serviceName = strTxt[0].ToString() + ";Asire.Pan.Common.WorkFlowNotificationServices;" + strTxt[2].ToString();
permissionId = workFlowServiceDetail;
return userLists;
}
this is mainly because of the " return userList". so how can i make the loop run again. or please suggest some way to make it work.Is it possible to copy that returning userList to some List and return it after the loop.If so how can i write i list there. Please help me..?
Remove return in Foreach loop
var userListsTemp=null;
foreach (int workFlowServiceDetail in workFlowServiceDetails)
{
using (var db = new AdminDb())
{
string workFlowServiceDtl = (from perm in db.WorkFlowPermission.AsNoTracking()
where perm.WorkFlowPermissionId == workFlowServiceDetail
select perm.Service).FirstOrDefault();
//to select eligibility rules against this service
string eligibility = (from definition in db.WorkFlowDefinition.AsNoTracking()
join model in db.WorkFlowModel.AsNoTracking()
on definition.WorkFlowDefinitionId equals model.WorkFlowDefinitionId
join permission in db.WorkFlowPermission.AsNoTracking()
on model.WorkFlowDefinitionId equals permission.WorkFlowDefinitionId
where model.ControllerNameId.Equals(current_ControllerId) && permission.WorkFlowPermissionId == workFlowServiceDetail
select permission.EligibilityRule).FirstOrDefault();
if (eligibility == null)
{
string validationMessage = "";
validationMessage = "Please set eligibility for workflow permission";
serviceName = null;
permissionId = 0;
return new CustomBusinessServices() { strMessage = validationMessage };
}
string[] strTxt = workFlowServiceDtl.Split(';'); //split the service name by ';' and strore it in an array
string serviceUrl = string.Empty;
string workFlowServiceName = string.Empty;
string classpath = string.Empty;
workFlowServiceName = strTxt[0].ToString();
workFlowServiceName = workFlowServiceName.Replace(" ", "");//get the service name by removing empty blank space for the word
classpath = strTxt[1].ToString();
//Invoke REST based service (like Node.Js service)
if (strTxt.Length == 4)
{
serviceUrl = strTxt[3].ToString();
}
//Invoke c# based service
else
{
serviceUrl = string.Empty;
}
var userLists = PermissionCallMethod(classpath, workFlowServiceName, new[] { workFlowImplemented, eligibility }, serviceUrl);
/*****************************************Problem in this loop**********/
if (userLists.UserList.Contains(userId))
{
serviceName = strTxt[0].ToString() + ";Aspir.Pan.Common.WorkFlowNotificationServices;" + strTxt[2].ToString();
permissionId = workFlowServiceDetail;
//return userLists;
if(userListsTemp==null)
{
userListsTemp=userLists;
}
else
{
userListsTemp.Concat(userLists).ToList();
}
}
}
}
serviceName = string.Empty;
permissionId = 0;
return null;

How to find Customer Entities logical name from Guid in Microsoft CRM

In CRM I am trying to automate the process of creating a new email from a previous email in the chain. This email has to go to the customer of the case, who could be either an account or a contact.
I can retrieve the Guid of the contact/account but I dont know how to retrieve the logical name.
This is what I have so far:
OrganizationServiceProxy service = CRMCentralCRMServiceInstance;
Guid customerId = GetCustomerIdFromCase(caseId);
Entity email = new Entity("email");
Entity activityPartyTo = new Entity("activityparty");
//"account" is a guess, it could be "contact"
EntityReference customerReferenceTo = new EntityReference("account", customerId);
activityPartyTo["partyid"] = customerReferenceTo;
EntityCollection toEntityCollection = new EntityCollection();
toEntityCollection.Entities.Add(activityPartyTo);
email["to"] = toEntityCollection;
.
.
.
newEmailId = service.Create(email);
public Guid GetCustomerIdFromCase(Guid caseId) {
Guid customerId = Guid.Empty;
List<CRMCase> caseList = GetCRMCasesById(caseId);
if (caseList.Count > 0)
{
CRMCase cmcCase = caseList.First();
customerId = cmcCase.CustomerId;
}
return (customerId);
}
public List<CRMCase> GetCRMCasesById(Guid caseId)
{
List<CRMCase> crmCases = new List<CRMCase>();
try
{
OrganizationServiceProxy service = CRMCentralCRMServiceInstance;
ConditionExpression condition1 = new ConditionExpression();
ConditionExpression condition2 = new ConditionExpression();
condition1.AttributeName = "incidentid";
condition1.Operator = ConditionOperator.Equal;
condition1.Values.Add(caseId.ToString("N"));
condition2.AttributeName = "statecode";
condition2.Operator = ConditionOperator.In;
condition2.Values.Add("Active");
condition2.Values.Add("Resolved");
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.Conditions.Add(condition1);
filter.Conditions.Add(condition2);
QueryExpression query = new QueryExpression();
query.EntityName = "incident";
query.ColumnSet = new ColumnSet(true);
query.Criteria = filter;
RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest();
retrieveAttributeRequest.EntityLogicalName = "incident";
retrieveAttributeRequest.LogicalName = "statuscode";
retrieveAttributeRequest.RetrieveAsIfPublished = true;
RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);
StatusAttributeMetadata statusCodeAttribute = (StatusAttributeMetadata)retrieveAttributeResponse.AttributeMetadata;
retrieveAttributeRequest = new RetrieveAttributeRequest();
retrieveAttributeRequest.EntityLogicalName = "incident";
retrieveAttributeRequest.LogicalName = "prioritycode";
retrieveAttributeRequest.RetrieveAsIfPublished = true;
retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);
PicklistAttributeMetadata priorityCodeAttribute = (PicklistAttributeMetadata)retrieveAttributeResponse.AttributeMetadata;
retrieveAttributeRequest = new RetrieveAttributeRequest();
retrieveAttributeRequest.EntityLogicalName = "incident";
retrieveAttributeRequest.LogicalName = "statecode";
retrieveAttributeRequest.RetrieveAsIfPublished = true;
retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);
StateAttributeMetadata stateCodeAttribute = (StateAttributeMetadata)retrieveAttributeResponse.AttributeMetadata;
EntityCollection casesColl = service.RetrieveMultiple(query);
foreach (Entity entity in casesColl.Entities)
{
Entity incidentCRMCase = entity;
CRMCase cRMCase = GetCRMCaseFromIncidentCase(incidentCRMCase, statusCodeAttribute.OptionSet.Options, stateCodeAttribute.OptionSet.Options, priorityCodeAttribute.OptionSet.Options);
crmCases.Add(cRMCase);
}
}
catch (SoapException se)
{
string action = MethodBase.GetCurrentMethod().DeclaringType.Name + " :: " + MethodBase.GetCurrentMethod().Name;
string message = "Unexpected error in action: " + action
+ Environment.NewLine + se.Message
+ Environment.NewLine + se.Detail.InnerText;
throw new Exception(message);
}
return (crmCases);
}
I found this brute force method but I would rather find a cleaner way if there is.
Ok. Really complicated code. Try to use something like following:
private EntityReference GetCustomerFromCase(Guid caseId)
{
Entity Case = CRMCentralCRMServiceInstance.Retrieve("incident", caseId, new ColumnSet("customerid"));
return Case.GetAttributeValue<EntityReference>("customerid");
}

Error when returning value in C# 2.0

I downloaded an example application for using some web services with an online system.
I am not sure if all code below is needed but it is what I got and what I am trying to do is to use the search function.
I start by calling searchCustomer with an ID I have:
partnerRef.internalId = searchCustomer(customerID);
And the code for searchCustomer:
private string searchCustomer(string CustomerID)
{
string InternalID = "";
CustomerSearch custSearch = new CustomerSearch();
CustomerSearchBasic custSearchBasic = new CustomerSearchBasic();
String nameValue = CustomerID;
SearchStringField entityId = null;
entityId = new SearchStringField();
entityId.#operator = SearchStringFieldOperator.contains;
entityId.operatorSpecified = true;
entityId.searchValue = nameValue;
custSearchBasic.entityId = entityId;
String statusKeysValue = "";
SearchMultiSelectField status = null;
if (statusKeysValue != null && !statusKeysValue.Trim().Equals(""))
{
status = new SearchMultiSelectField();
status.#operator = SearchMultiSelectFieldOperator.anyOf;
status.operatorSpecified = true;
string[] nskeys = statusKeysValue.Split(new Char[] { ',' });
RecordRef[] recordRefs = new RecordRef[statusKeysValue.Length];
for (int i = 0; i < nskeys.Length; i++)
{
RecordRef recordRef = new RecordRef();
recordRef.internalId = nskeys[i];
recordRefs[i] = recordRef;
}
status.searchValue = recordRefs;
custSearchBasic.entityStatus = status;
}
custSearch.basic = custSearchBasic;
SearchResult response = _service.search(custSearch);
if (response.status.isSuccess)
{
processCustomerSearchResponse(response);
if (seachMoreResult.status.isSuccess)
{
processCustomerSearchResponse(seachMoreResult);
return InternalID;
}
else
{
_out.error(getStatusDetails(seachMoreResult.status));
}
}
else
{
_out.error(getStatusDetails(response.status));
}
return InternalID;
}
In the code above processCustomerSearchResponse gets called
processCustomerSearchResponse(response);
The code for this function is:
public string processCustomerSearchResponse(SearchResult response)
{
string InternalID = "";
Customer customer;
customer = (Customer)records[0];
InternalID = customer.internalId;
return InternalID;
}
What the original code did was to write some output in the console but I want to return the InternalID instead. When I debug the application InternalID in processCustomerSearchResponse contains the ID I want but I don't know how to pass it to searchCustomer so that function also returns the ID. When I debug searchCustomer InternalID is always null. I am not sure on how to edit the code under response.status.isSuccess
to return the InternalID, any ideas?
Thanks in advance.
When you call processCustomerSearchResponse(response);, you need to store the return value in memory.
Try modifying your code like this:
InternalID = processCustomerSearchResponse(response);

Retrieve Dynamics CRM custom fields using Webservice query

I'm trying to pull information from a CRM installation and so far this is fine for using the default fields. However I'm having difficulty retrieving custom fields, for example Contacts have a custom field called web_username.
My code at present is
QueryExpression query = new QueryExpression();
query.EntityName = "contact";
ColumnSet cols = new ColumnSet();
cols.Attributes = new string[] { "firstname", "lastname" };
query.ColumnSet = cols;
BusinessEntityCollection beReturned = tomService.RetrieveMultiple(query);
foreach (contact _contact in beReturned.BusinessEntities)
{
DataRow dr = dt.NewRow();
dr["firstname"] = _contact.firstname;
dr["lastname"] = _contact.lastname;
dt.Rows.Add(dr);
}
How do I include custom fields in my query? I've tried searching around but with no luck yet but I could be searching incorrectly as I'm not used to CRM terms.
Cheers in advance!
I've since been able to solve this. In case it is of use to anyone else this is what I did. The query is set up as before except I've added my custom field to the ColumnSet.
cols.Attributes = new string[] { "firstname", "lastname", "new_web_username" };
And then used RetrieveMultipleResponse and Request with ReturnDynamicEntities set to true
RetrieveMultipleResponse retrived = new RetrieveMultipleResponse();
RetrieveMultipleRequest retrive = new RetrieveMultipleRequest();
retrive.Query = query;
retrive.ReturnDynamicEntities = true;
retrived = (RetrieveMultipleResponse)tomService.Execute(retrive);
Please still comment if there is a better way for me to do this.
EDIT
Using the example in my original question if you cast to a contact
contact myContact = (contact)myService.Retrieve(EntityName.contact.ToString(), userID, cols);
You can then access properties of the object
phone = myContact.telephone1;
password = myContact.new_password;
If you update your CRM webreference custom fields you've added in CRM are available.
public List<Entity> GetEntitiesCollection(IOrganizationService service, string entityName, ColumnSet col)
{
try
{
QueryExpression query = new QueryExpression
{
EntityName = entityName,
ColumnSet = col
};
var testResult = service.RetrieveMultiple(query);
var testResultSorted = testResult.Entities.OrderBy(x => x.LogicalName).ToList();
foreach (Entity res in testResultSorted)
{
var keySorted = res.Attributes.OrderBy(x => x.Key).ToList();
DataRow dr = null;
dr = dt.NewRow();
foreach (var attribute in keySorted)
{
try
{
if (attribute.Value.ToString() == "Microsoft.Xrm.Sdk.OptionSetValue")
{
var valueofattribute = GetoptionsetText(entityName, attribute.Key, ((Microsoft.Xrm.Sdk.OptionSetValue)attribute.Value).Value, _service);
dr[attribute.Key] = valueofattribute;
}
else if (attribute.Value.ToString() == "Microsoft.Xrm.Sdk.EntityReference")
{
dr[attribute.Key] = ((Microsoft.Xrm.Sdk.EntityReference)attribute.Value).Name;
}
else
{
dr[attribute.Key] = attribute.Value;
}
}
catch (Exception ex)
{
Response.Write("<br/>optionset Error is :" + ex.Message);
}
}
dt.Rows.Add(dr);
}
return testResultSorted;
}
catch (Exception ex)
{
Response.Write("<br/> Error Message : " + ex.Message);
return null;
}
}
//here i have mentioned one another function:
var valueofattribute = GetoptionsetText(entityName, attribute.Key, ((Microsoft.Xrm.Sdk.OptionSetValue)attribute.Value).Value, _service);
//definition of this function is as below:
public static string GetoptionsetText(string entityName, string attributeName, int optionSetValue, IOrganizationService service)
{
string AttributeName = attributeName;
string EntityLogicalName = entityName;
RetrieveEntityRequest retrieveDetails = new RetrieveEntityRequest
{
EntityFilters = EntityFilters.All,
LogicalName = entityName
};
RetrieveEntityResponse retrieveEntityResponseObj = (RetrieveEntityResponse)service.Execute(retrieveDetails);
Microsoft.Xrm.Sdk.Metadata.EntityMetadata metadata = retrieveEntityResponseObj.EntityMetadata;
Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata picklistMetadata = metadata.Attributes.FirstOrDefault(attribute => String.Equals(attribute.LogicalName, attributeName, StringComparison.OrdinalIgnoreCase)) as Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata;
Microsoft.Xrm.Sdk.Metadata.OptionSetMetadata options = picklistMetadata.OptionSet;
IList<OptionMetadata> OptionsList = (from o in options.Options
where o.Value.Value == optionSetValue
select o).ToList();
string optionsetLabel = (OptionsList.First()).Label.UserLocalizedLabel.Label;
return optionsetLabel;
}

Categories