conorjgallagher / Dynamics.ExtendedSvcUtil

Extension of the CrmSvcUtil to allow more custom creation of early bound types
5 stars 2 forks source link

Option set display name #4

Open katymariehughes opened 5 years ago

katymariehughes commented 5 years ago

I also had another question if possible!

I am attempting to modify your solution slightly so that I can apply a display name attribute above each enum value based on the option set value label, but I'm unsure if I can get it without calls to CRM.

in CodeCustomizationService.cs : 83 I have added the bit between the // -------

// Now that we know what optionsets need to be included create the adequate files for them
for (var j = 0; j < types.Count; j++)
{
     var type = types[j];

     EnumAttributeMetadata optionSet = GetIncludedOptionSet(type.Name);
     if (type.IsEnum && optionSet != null)
     {
          EntitySchema entity = GetSchemaEntity(optionSet.EntityLogicalName);
          var entityGroup = entity.FriendlyName;
          if (optionSet.OptionSet.IsGlobal.Value)
          {
               entityGroup = "Global";
          }
          if (!optionSets.ContainsKey(entityGroup))
          {
               optionSets[entityGroup] = new List<CodeTypeDeclaration>();
          }
          if (optionSets[entityGroup].Any(t => t.Name == type.Name) == false)
          {
              // ------------------
              foreach (CodeMemberField member in type.Members)
              {   
                  member.CustomAttributes.Add(new CodeAttributeDeclaration("System.ComponentModel.DataAnnotations.Display", new CodeAttributeArgument("Name", new CodePrimitiveExpression(member.Name))));
              }
              // ------------------
              optionSets[entityGroup].Add(type);
          }
     }
}

This generates the below as expected


[System.Runtime.Serialization.DataContractAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("CrmSvcUtil", "8.0.0000.2074")]
public enum ApplicationFormType {

    [System.Runtime.Serialization.EnumMemberAttribute()]
    [System.ComponentModel.DataAnnotations.Display(Name="Applicationforpermissionandconsent_P1")]
    Applicationforpermissionandconsent_P1 = 158710000,

    [System.Runtime.Serialization.EnumMemberAttribute()]
    [System.ComponentModel.DataAnnotations.Display(Name="Applicationforchangestoyourhome_P2")]
    Applicationforchangestoyourhome_P2 = 158710001,
}

but I would like to be able to grab the display label text from CRM to give e.g.


[System.Runtime.Serialization.DataContractAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("CrmSvcUtil", "8.0.0000.2074")]
public enum ApplicationFormType {

    [System.Runtime.Serialization.EnumMemberAttribute()]
    [System.ComponentModel.DataAnnotations.Display(Name="(P1) Permission and Consent")]
    Applicationforpermissionandconsent_P1 = 158710000,

    [System.Runtime.Serialization.EnumMemberAttribute()]
    [System.ComponentModel.DataAnnotations.Display(Name="(P2) Changes to your home")]
    Applicationforchangestoyourhome_P2 = 158710001,
}

so my question is, is there any data available to me at this point in the code that contains the OptionMetadata so that I may do e.g. metadata.Label.UserLocalizedLabel.Label; ?

I have tried making my own connection to CRM and doing metadata requests but it must just be bombing out silently as the entities and enum files do not get generated. I don't really understand well enough how the svcutil filters work, and I can't find any answers online.

Thanks so much for any help!

conorjgallagher commented 5 years ago

I can't 100% confirm as I'm unfortunately not at Visual Studio right now. But there might be a label coming through on the metadata. This line here potentially pulls back all the metadata for the optionset, including underlying options metadata:

EnumAttributeMetadata optionSet = GetIncludedOptionSet(type.Name);

You could be able to interrogate the underlying options metadata which is stored here:

optionSet.OptionSet.Options

That would potentially have a list of the options metadata and hence find the relevant label for the option you need.

If that doesn't work then perhaps there is another way to get that information stored in the schema during the filtering process in the CodeWriterFilter class here:

GenerateOption(OptionMetadata optionMetadata, IServiceProvider services)

Before calling the default service to generate the option you potentially could store the option away like I do for the optionset itself. Just don't remove the line "return _defaultService.GenerateOption(optionMetadata, services);"as I have a memory of it not working very well without it!