ASPNET MVC – 使用具有相同签名的新助手覆盖Html.TextBoxFor(model.property)?

我想用我自己的帮助器覆盖Html.TextBoxFor(),该帮助器具有完全相同的签名(当然是一个不同的命名空间) – 这是可能的,如果是这样,怎么样?

这样做的原因是我在现有应用程序中有100多个视图,我想改变TextBoxFor的行为,以便在属性具有[StringLength(n)]注释时输出maxLength = n属性。

自动输出maxlength = n的代码在这个问题中: 来自Asp.Net MVC中DataAnnotations StringLength的文本框的maxlength属性 。 但我的问题并不重复 – 我正在尝试创建一个更通用的解决方案:DataAnnotaion自动流入html,而不需要编写视图的人员需要额外的代码。

在引用的问题中,您必须将每个Html.TexBoxFor更改为Html.CustomTextBoxFor。 我需要这样做,以便不需要更改现有的TextBoxFor() – 因此创建一个具有相同签名的帮助程序:更改辅助方法的行为,并且所有现有实例都可以正常工作而不做任何更改(100 + views,至少500 TextBoxFor()s – 不想手动编辑它)。

我尝试了这段代码:(我需要为TextBoxFor的每次重载重复它,但一旦根问题解决了,那将是微不足道的)

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

但是我在Html.TextBoxFor()视图中遇到编译器错误:“调用在以下方法或属性之间是不明确的”(当然)。 有没有办法做到这一点?

是否有一种替代方法可以让我改变Html.TextBoxFor的行为,以便不需要更改已经使用它的视图?

您不能同时拥有两个具有相同名称和相同签名的扩展方法。 您可以将扩展方法放入自定义命名空间,并使用此命名空间而不是web.config中的默认命名空间(System.Web.Mvc.Html):

       

但是如果你这样做,你将失去所有其他扩展方法,你需要在自定义命名空间中覆盖它们。

简短的回答,不,你不能“替换”现有的扩展方法。

更长的答案,你可能会通过一些非常邪恶的反思来做到这一点……虽然我非常怀疑这甚至会起作用。 这些方面的东西:

  // 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); } } } 

您可以使用editortemplate和自定义ModelMetadataProvider来解决此问题。 (很抱歉没有提供更多信息,虽然这非常适合Google,我希望这会让你朝着正确的方向前进。)