3

So, there are tons of examples of making custom data validators, but what I need is a Data Annotation that will just add an attribute to the final markup. My google-fu must just be weak today. The basic idea would be:

Model.cs

[SomeCustomAttribute]
public int CoolProperty {get;set}

View.cshtml

@Html.EditorFor(q => q.CoolProperty)

Then, the magical Wizardry ensues here:

public class SomeCustomAttribute : SomeAwesomeClassToInheritThatICantFind {
  public override void AddAttributes() {
     AddAttribute("CustomAttribute");
  }
}

And, finally I'd like the markup rendered as:

<input type="text" CustomAttribute>

Obviously it'd be more complicated, but that's the gist of it. I know i can just chuck this in the view, but I'm going to be reusing this particular logic all over the place and it seems like there should be some way to do this. Something similar to the Display attribute.

If there's another approach that I'm missing, I'm all for that as well.

Rob
  • 2,080
  • 4
  • 28
  • 48
  • What is the ultimate goal ?, maybe there is a more correct way to achieve your goal. – Orel Eraki Dec 09 '15 at 17:22
  • The goal is to be able to use the Custom attribute on many of my properties (in mutliple models) and have it spew out attributes into the html of the rendered tag. If I can get something close, I probably can take it from there, but I can't even find a class that I can start to inherit from. After that I would want to be able to query stuff on the server and use that to drive what the attribute would be. That part is trivial though. – Rob Dec 09 '15 at 17:26
  • This may answer or guide you: http://stackoverflow.com/questions/129285/can-attributes-be-added-dynamically-in-c – Orel Eraki Dec 09 '15 at 17:32
  • I looked at that and it didn't seem to get what I needed, but I might have a solution anyway doing it a bit differently. If I can get your link to work or @rcompanhoni 's I'll respond accordingly – Rob Dec 09 '15 at 20:41
  • The HtmlHelpers generate html attributes from known validation attributes (`data-*`). You can have you attribute implement `IMetadataAware` and add the attributes you want to `metadata.AdditionalValues` but then you have to create your own extension methods to generate the html. –  Dec 10 '15 at 04:12
  • @StephenMuecke, That might do what I need... I'll try that as well. – Rob Dec 10 '15 at 13:35

2 Answers2

0

You could use a custom editor template:

1) Create the folder /Views/Shared/EditorTemplates

2) Create inside this folder the file SomeCustomAttributes.cshtml

3) In the template file you'll have to specify the type to which the template can be applied and the rules (adding an @Html.TextBox with two attributes, class and maxlength):

@model int

@Html.TextBox("", (Model), new { @class = "someClass" , maxlength="5"})

4) Finally,use the UIHint attribute to specify the custom template:

[UIHint("SomeCustomAttributes")]
public int CoolProperty {get;set}

You should get an input type=text with attributes class=someClass and maxlength=5

Rafael Companhoni
  • 1,780
  • 1
  • 15
  • 31
0

This may also be a good candidate for a custom HTML Helper method - this would allow you to reuse it in other areas of your application. This is what I did to mimic the standard ActionLink method; mine allows me to specify bootstrap glyphicon classes.

  1. Create a static class to hold your html helper method(s); mine is called HtmlHelpers.

  2. Inside this class, define and implement a static method that encapsulates the logic you need. I called my method BootstrapActionLink. Because this is an extension method, the first parameter needs to be this HtmlHelper parameterName.

  3. Since you want to reuse in different areas of your application, you will want to add the class namespace (step 1) to the web.config file located in the ~/Views folder (not the top-level web.config).

  4. You can now use your HTML helper method in any of your views.

Below is my helper method code that makes use of the TagBuilder class:

public static MvcHtmlString BootstrapActionLink(this HtmlHelper htmlHelper, string linkText, string linkUrl, string bootstrapClasses, string glyphClasses)
{
    TagBuilder anchor = new TagBuilder("a");
    anchor.MergeAttribute("href", linkUrl);
    anchor.AddCssClass(bootstrapClasses);

    TagBuilder span = new TagBuilder("span");
    span.AddCssClass(glyphClasses);

    anchor.InnerHtml = linkText + " " + span.ToString();

    return MvcHtmlString.Create(anchor.ToString());
}

Inside ~/Views/Web.config I have

<system.web.webPages.razor>
    ...
    <namespaces>
        <add namespace="ApplicationName.NamespaceName"/>

In my views I use the following code

@Html.BootstrapActionLink("Add Account", @Url.Action("Add", new { employeeId = @Model.EmployeeId.Trim() }), "btn btn-primary", "glyphicon glyphicon-plus")

The generated output looks like this:

<a class="btn btn-primary" href="/myapplication/Add/123456">Add Account <span class="glyphicon glyphicon-plus"></span></a>
  • Brilliant... Not exactly what I wanted, but this is close enough for my needs..t hanks so much – Rob Dec 12 '15 at 03:04