Nick Kahn
Nick Kahn

Reputation: 20078

How to get the StringLength from DataAnnotations

After updating the suggestion I'm still getting the error

Tried both with .SingleOrDefault() or FirstOrDefault()

enter image description here

I need to retrieve the StringLength annotation value and here is my code but I'm getting the following error.

I have tried to implement pretty much the same code from here but getting the error:

Sequence contains no elements

    public static class DataAnnotation
    {
        public static int GetMaxLengthFromStringLengthAttribute(Type modelClass, string propertyName)
        {
            int maxLength = 0;
            var attribute = modelClass.GetProperties()
                            .Where(p => p.Name == propertyName)
                            .Single()
                            .GetCustomAttributes(typeof(StringLengthAttribute), true)
                            .Single() as StringLengthAttribute;

            if (attribute != null)
                maxLength = attribute.MaximumLength;

            return 0;
        }
    }

//calling:

int length = DataAnnotation.GetMaxLengthFromStringLengthAttribute(typeof(EmployeeViewModel), "Name");


public class EmployeeViewModel
{         
    [StringLength(20, ErrorMessage = "Name cannot be longer than 20 characters.")] 
    public string Name{ get; set; }
}

Upvotes: 12

Views: 9252

Answers (5)

Richard Griffiths
Richard Griffiths

Reputation: 836

As I was just tackling this, I thought I'd provide the LinqPad code I'm playing around with. It is complete enough to run in Linqpad, just add the imports if you want to explore.

Note where I comment the bit you actually need. I've found it tricky sometimes to adapt code without some context.

///The rest of the code given as context as I'm working on a T4 template to create Model classes from Datalayer classes, so the iteration is required in my case
void Main()
{
    CVH p = new CVH();
    Type t = p.GetType();

    foreach (PropertyInfo prop in t.GetProperties()) //Iterating through properties
    {
        foreach (var facet in prop.GetCustomAttributes()) //Yank out attributes
        {
        //The bit you need
            if ((Type)facet.TypeId == typeof(StringLengthAttribute)) //What type of attribute is this? 
            {
                StringLengthAttribute _len = (StringLengthAttribute)facet; //Cast it to grab Maximum/MinimumLengths etc.
                Console.WriteLine($"My maximum field length is { _len.MaximumLength}");
                //End of the bit you need
                Console.WriteLine(_len.MinimumLength);              
            }
        }
    }
}
///Test class with some attributes
public class CVH
{
    [StringLength(50)]
    [DataType(DataType.PhoneNumber)]
    public string phone_1 { get; set; }
    [Required(ErrorMessage = "id is required")]
    public int id { get; set; }
    [Required(ErrorMessage = "id is required")]
    public int contact_id { get; set; }
}

Upvotes: 0

Andriy Tolstoy
Andriy Tolstoy

Reputation: 6100

var maxLength = typeof(EmployeeViewModel)
                    .GetProperty("Name")
                    .GetCustomAttributes<StringLengthAttribute>()
                    .FirstOrDefault()
                    .MaximumLength;

Upvotes: 1

Nick Kahn
Nick Kahn

Reputation: 20078

I able to figured out, tested and its working great, in case if anybody else is looking!

  StringLengthAttribute strLenAttr = typeof(EmployeeViewModel).GetProperty(name).GetCustomAttributes(typeof(StringLengthAttribute), false).Cast<StringLengthAttribute>().SingleOrDefault();
  if (strLenAttr != null)
  {
     int maxLen = strLenAttr.MaximumLength;
  }

Upvotes: 12

Rahul Tripathi
Rahul Tripathi

Reputation: 172588

You can get the answer from When you get theLINQ Error “Sequence contains no elements”, this is usually because you are using the First() or Single() command rather than FirstOrDefault() and SingleOrDefault().

So you need to try using SingleOrDefault() instead of Single() like

var attribute = modelClass.GetProperties()
                            .Where(p => p.Name == propertyName)
                            .SingleOrDefault()
                            .GetCustomAttributes(typeof(StringLengthAttribute), true)
                            .SingleOrDefault() as StringLengthAttribute;

Upvotes: 3

heymega
heymega

Reputation: 9411

Are you trying to show length as part of the error message? If so I believe you can just put...

public class EmployeeViewModel
{         
    [StringLength(20, ErrorMessage = "{0} cannot be longer than {1} characters.")] 
    public string Name{ get; set; }
}

Upvotes: 0

Related Questions