ASPNET MVC - override Html.TextBoxFor (model.property) with a new helper with the same signature?

I want to override Html.TextBoxFor () with my own helper, which has exactly the same signature (but, of course, a different namespace) - is this possible, and if so, how?

The reason for this is that I have more than 100 views in an existing application, and I want to change the behavior of TextBoxFor so that it displays the attribute maxLength = n if the property has the annotation [StringLength (n)].

The code for automatically output maxlength = n is in this question: the maxlength attribute of a text field from DataAnnotations StringLength in Asp.Net MVC . But my question is not a duplicate - I'm trying to create a more general solution: where DataAnnotaion automatically flows into html, without the need for additional code to be used by the person who writes the presentation.

In the question mentioned, you need to change each Html.TexBoxFor to Html.CustomTextBoxFor. I need to do this so that the existing TextBoxFor () does not need to be changed - therefore, creating an assistant with the same signature: change the behavior of the helper method and all existing instances will work without any changes (100+ views, at least 500 TextBoxFor () s - do not want to manually edit this).

I tried this code: (And I need to repeat it for each TextBoxFor overload, but as soon as the problem with the root is solved, it will be trivial)

namespace My.Helpers { public static class CustomTextBoxHelper { public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, bool includeLengthIfAnnotated) { // implementation here } } } 

But I get a compiler error in the view on Html.TextBoxFor (): "The call is ambiguous between the following methods or properties" (of course). Is there any way to do this?

Is there an alternative approach that would allow me to change the behavior of Html.TextBoxFor, so now I don’t need to change existing views?

+7
c # asp.net-mvc html-helper data-annotations
source share
3 answers

You cannot have two extension methods with the same name and the same signature at the same time. You can put your extension method in a custom namespace and use that namespace instead of the standard one (System.Web.Mvc.Html) in your web.config:

 <pages> <namespaces> <!--<add namespace="System.Web.Mvc.Html"/>--> <add namespace="YourCompany.Web.Mvc.Html"/> </namespaces> </pages> 

but if you do, you will lose all other extension methods, and you will need to override them in your user namespace.

+4
source share

The short answer is no, you cannot "replace" an existing extension method.

The answer is longer, you could do it with some kind of extremely evil reflection ... Although I very much doubt that even this will work. Something like that:

  // Get the handle for the RuntimeMethodInfo type var corlib = Assembly.GetAssembly(typeof (MethodInfo)); var corlibTypes = corlib.GetModules().SelectMany(mod => mod.FindTypes((a, b) => true, null)); Type rtmiType = corlibTypes.Where(t => t != null && t.FullName != null && t.FullName.Contains("Reflection.RuntimeMethodInfo")).First(); // Find the extension method var methods = typeof (Html).GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (var methodInfo in methods) { if (methodInfo.Name == "TextBoxFor") { // Try to monkeypatch this to be private instead of public var methodAttributes = rtmiType.GetField("m_methodAttributes", BindingFlags.NonPublic | BindingFlags.Instance); if(methodAttributes != null) { var attr = methodAttributes.GetValue(methodInfo); attr = ((MethodAttributes)attr) | MethodAttributes.Private; methodAttributes.SetValue(methodInfo, attr); } } } 
+1
source share

You can solve this with editortemplate and custom ModelMetadataProvider. (Sorry for not providing more information, although this is entirely possible for Googleable, and I hope this puts you in the right direction.)

-3
source share

All Articles