4

So let's say I have a small model object that contains a string that's required and has a max length of 50:

public class ObjectModel
{
    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}

I need to create a custom HTML helper where I can pass in a string (in this case, ObjectModel.Name) and if it's required, create an HTML input element with class "required".

Right now, I'm trying to work with:

 public static HtmlString Input(string label)
 {
     return new HtmlString("<input type=\"text\" />");
 }

So in my Razor view, if I do something like @InputHelper.Input(Model.Name), I can't access the attributes. My question is, how do I structure my HTML helper class to accept a Model property along with its attributes?

So I've made further progress, but I'm still not experienced enough to navigate through expressions to get what I want. Right now, I have:

@InputHelper.Input(m => Model.Title.TitleName, "titlename2", "Title Name")

The second and third parameters are irrelevant to this question. And in the helper method, I have:

public static HtmlString Input(Expression<Func<string, Object>> expression, string id, string label)

But when I go to debug the code, there are so many objects and properties to sift through that I have no idea where my Required and MaxLength attributes are, if they're even in there.

Jay Sun
  • 1,583
  • 3
  • 25
  • 33

2 Answers2

2

You can get your Required and MaxLength attributes using the following extension method:

public static class ExpressionExtensions
{
    public static TAttribute GetAttribute<TIn, TOut, TAttribute>(this Expression<Func<TIn, TOut>> expression) where TAttribute : Attribute
    {
        var memberExpression = expression.Body as MemberExpression;
        var attributes = memberExpression.Member.GetCustomAttributes(typeof(TAttribute), true);
        return attributes.Length > 0 ? attributes[0] as TAttribute : null;
    }
}

Then from your code you can do:

public static HtmlString Input(Expression<Func<string, Object>> expression, string id, string label)
{
    var requiredAttribute = expression.GetAttribute<string, object, RequiredAttribute>();
    if (requiredAttribute != null) 
    {
        // some code here
    }
}
RJ Cuthbertson
  • 1,458
  • 1
  • 20
  • 36
Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
  • Didn't work for me. Casting `expression.Body` to `MemberExpression` returns `null`. – Jakov Feb 13 '18 at 15:10
  • @Jakov please can you post another question with this (with a code snippet) - I'd venture that the expression that you're passing into this function is incorrect – Rich O'Kelly Feb 22 '18 at 15:54
0

You have to look at what they did with the .NET framework. Create a method that takes an Expression>, and then use code to extract the name of the property from the helper:

Community
  • 1
  • 1
Brian Mains
  • 50,520
  • 35
  • 148
  • 257