Reputation: 20078
After updating the suggestion I'm still getting the error
Tried both with .SingleOrDefault()
or FirstOrDefault()
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
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
Reputation: 6100
var maxLength = typeof(EmployeeViewModel)
.GetProperty("Name")
.GetCustomAttributes<StringLengthAttribute>()
.FirstOrDefault()
.MaximumLength;
Upvotes: 1
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
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
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