2

Hi I am wondering if there is a straight forward way to retrieve the value of a custom attribute in my model VIA a controller. For arugment sake...let's say I have this in my model:

[DisplayName("A name")]
public string test;

In my controller I want to retrieve "A name" by using something similar to this:

ModelName.test.Attributes("DisplayName").value

Is it something fanciful?

Thanks in advance.
WML

WML
  • 173
  • 13

3 Answers3

3

Here is a good article on how to retrieve values from attributes. I don't think there is any other way to do this beyond reflection.

From the article (just change the Attribute type for your example :)):

   public static void PrintAuthorInfo(Type t) 
   {
      Console.WriteLine("Author information for {0}", t);
      Attribute[] attrs = Attribute.GetCustomAttributes(t);
      foreach(Attribute attr in attrs) 
      {
         if (attr is Author) 
         {
            Author a = (Author)attr;
            Console.WriteLine("   {0}, version {1:f}",
a.GetName(), a.version);
         }
      }
   }
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
  • To the anonymous downvoter, please let me know why you have downvoted my answer? I cannot fix any perceived errors if I do not know what the problem is... – Justin Pihony Apr 19 '12 at 04:23
  • Thanks for the inspiration answer....I have created a routine which is based on the [link]http://msdn.microsoft.com/en-us/library/system.attribute(v=vs.90).aspx article and use reflection to interrogate the propertyInfo. I read more about the GetCustomAttributes and basically got similar to your routine. Thanks a lot. – WML Apr 20 '12 at 01:06
1

Try this:

var viewData = new ViewDataDictionary<MyType>(/*myTypeInstance*/);
string testDisplayName = ModelMetadata.FromLambdaExpression(t => t.test, viewData).GetDisplayName();
Max Toro
  • 28,282
  • 11
  • 76
  • 114
  • it is my bad but what if the attribute is a custom attribute instead of DisplayName? What I was trying to do is to have a custom attribute [GroupId(2)] against a property (e.g. Test) in my model class. In this case, I try to relate "Test has a groupId of 2". I can achieve the same thing by simply create another property but I think it is a bit more neat to do it as an attribute. My apologies of not very familiar with the concept of attribute. Should read up more. – WML Apr 19 '12 at 23:32
1

It is easy to do with reflection. Inside controller:

 public void TestAttribute()
    {
        MailJobView view = new MailJobView();
        string displayname = view.Attributes<DisplayNameAttribute>("Name") ;


    }

Extension:

   public static class AttributeSniff
{
    public static string Attributes<T>(this object inputobject, string propertyname) where T : Attribute
    {
        //each attribute can have different internal properties
        //DisplayNameAttribute has  public virtual string DisplayName{get;}
        Type objtype = inputobject.GetType();
        PropertyInfo propertyInfo = objtype.GetProperty(propertyname);
        if (propertyInfo != null)
        {
            object[] customAttributes = propertyInfo.GetCustomAttributes(typeof(T), true);

            // take only publics and return first attribute
            if (propertyInfo.CanRead && customAttributes.Count() > 0)
            {
                //get that first one for now

                Type ourFirstAttribute = customAttributes[0].GetType();
                //Assuming your attribute will have public field with its name
                //DisplayNameAttribute will have DisplayName property
                PropertyInfo defaultAttributeProperty = ourFirstAttribute.GetProperty(ourFirstAttribute.Name.Replace("Attribute",""));
                if (defaultAttributeProperty != null)
                {
                    object obj1Value = defaultAttributeProperty.GetValue(customAttributes[0], null);
                    if (obj1Value != null)
                    {
                        return obj1Value.ToString();
                    }
                }

            }

        }

        return null;
    }

}

I tested it works fine. It will use first attribute on that property. MailJobView class has a property named "Name" with DisplayNameAttribute.

Omer Cansizoglu
  • 1,271
  • 9
  • 14