1

I am trying to generate a dynamic form with question coming from a database. Each question has its type and other property.

Example of my classes:

    public class QuestionnaireBase
    {
        public string Text { get; set; }
        public int Sequence { get; set; }
    }       

    public abstract class Question : QuestionnaireBase
    {
        public bool IsRequired { get; set; }
        public bool WithComment { get; set; }
        public abstract object Answer { get; set; }
    }

    public class TextQuestion : Question
    {
        public string DefaultText { get; set; }
        public int MaxLength { get; set; }
        public override object Answer { get; set; }
    }

I would like add some attributes (DisplayAttribute, MaxLenght) to the Answer fields so the while i use EditorFor and LabelFor, those attributes are taken into account.

While retrieving my questions, I try to add an attribute on my field 'Answer' (here is a stub):

Enumerable.Range(1, 5).Select(questionSeq                                               => new TextQuestion {
Text = string.Format("Question {0}" questionSeq), 
Answer = "TEXTVALUE" + questionSeq
}).Select(w => {
   var skd = new DisplayAttribute();
   skd.Name =  w.Text; 
   TypeDescriptor.AddAttributes(w.Answer,skd );                                                 
   return w;
   })

Now, in my View, I would like to use LabelFor to display this DisplayAttribute:

 @Html.LabelFor(model => model.Questions[questionIndex].Answer)

This will output 'Answer' as text. I can bypass this problem by doing this:

   @{
     var attribute = 
TypeDescriptor.GetAttributes(Model.Questions[questionIndex].Answer)[typeof(DisplayAttribute)];

    var displayAttribute = ((DisplayAttribute) attribute);                          
    }
    @Html.LabelFor(model => 
model.Questions[questionIndex].Answer, displayAttribute.Name)

My first guess would be that, LabelFor would use the DisplayAttribute on my type, not on my instance.

Obviously, I do not want to have to do this work for every attributes or it's totally useless to create attributes at runtime.

What can I do to fix this problem ? I would like to do the same with MaxLenghtAttribute/Range. Thanks for your time

Tom
  • 944
  • 1
  • 14
  • 26
  • Have you looked at this? http://stackoverflow.com/questions/14663763/how-to-add-an-attribute-to-a-property-at-runtime – hbulens Nov 09 '16 at 22:28

1 Answers1

1

I don't think you'll be able to accomplish this exactly, since attributes are static metadata.

Can attributes be added dynamically in C#?

A possible workaround could be to create your own custom Attribute that implements all the possible validations (MaxLength, Range, etc.) and have some trigger attached to the object to enable/disable them. This would handle the validation, but not the specific instance mentioned in your question (Html.LabelFor + DisplayName). For that, you could create your own extension method that accesses the DisplayName attribute in the same manner that you add it to the instance.

Community
  • 1
  • 1
Wyatt Earp
  • 1,783
  • 13
  • 23