如何让 asp-for 输入标签助手生成驼峰命名法名称?
Posted
技术标签:
【中文标题】如何让 asp-for 输入标签助手生成驼峰命名法名称?【英文标题】:How to make the asp-for input tag helper generate camelCase names? 【发布时间】:2017-04-11 22:10:57 【问题描述】:如果我有这样的视图模型:
public class MyModel
public DateTime? StartDate get;set;
在视图中,输入标签与 asp-for 标签助手一起使用,如下所示:
<input asp-for="StartDate" />
由此生成的默认html是
<input type="datetime" id="StartDate" name="StartDate" value="" />
但我希望它生成的是如下所示的 html:
<input type="datetime" id="startDate" name="startDate" value="" />
如何让 asp-for 输入标签助手生成类似上面的骆驼案例名称 不必让我的模型属性为骆驼案例?
【问题讨论】:
你真的在乎吗?如果 taghelper 生成name="StartDate"
但您希望控制器方法使用名称 startDate
,则模型绑定器会为您处理。
我很在乎。因为我可以通过其 id 使用客户端 javascript 访问该字段,并且我希望该代码遵循我的代码库的编码约定。
【参考方案1】:
在研究了@Bebben 发布的代码和提供的链接之后,我继续深入挖掘 Asp.Net Core 源代码。而且我发现 Asp.Net Core 的设计者提供了一些扩展点,可以利用这些点来实现更低的驼峰式 id
和 name
值。
为此,我们需要实现我们自己的IHtmlGenerator
,我们可以通过创建一个继承自DefaultHtmlGenerator
的自定义类来实现。然后在那个类上,我们需要重写GenerateTextBox
方法来修复大小写。或者,我们可以覆盖GenerateInput
方法来修复所有输入字段(不仅仅是输入文本字段)的name
和id
属性值的大小写,这是我选择做的。作为奖励,我还覆盖了 GenerateLabel
方法,因此标签的 for
属性也使用自定义大小写指定了一个值。
课程如下:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Text.Encodings.Web;
namespace App.Web
public class CustomHtmlGenerator : DefaultHtmlGenerator
public CustomHtmlGenerator(
IAntiforgery antiforgery,
IOptions<MvcViewOptions> optionsAccessor,
IModelMetadataProvider metadataProvider,
IUrlHelperFactory urlHelperFactory,
HtmlEncoder htmlEncoder,
ClientValidatorCache clientValidatorCache) : base
(antiforgery, optionsAccessor, metadataProvider, urlHelperFactory,
htmlEncoder, clientValidatorCache)
//Nothing to do
public CustomHtmlGenerator(
IAntiforgery antiforgery,
IOptions<MvcViewOptions> optionsAccessor,
IModelMetadataProvider metadataProvider,
IUrlHelperFactory urlHelperFactory,
HtmlEncoder htmlEncoder,
ClientValidatorCache clientValidatorCache,
ValidationHtmlAttributeProvider validationAttributeProvider) : base
(antiforgery, optionsAccessor, metadataProvider, urlHelperFactory, htmlEncoder,
clientValidatorCache, validationAttributeProvider)
//Nothing to do
protected override TagBuilder GenerateInput(
ViewContext viewContext,
InputType inputType,
ModelExplorer modelExplorer,
string expression,
object value,
bool useViewData,
bool isChecked,
bool setId,
bool isExplicitValue,
string format,
IDictionary<string, object> htmlAttributes)
expression = GetLowerCamelCase(expression);
return base.GenerateInput(viewContext, inputType, modelExplorer, expression, value, useViewData,
isChecked, setId, isExplicitValue, format, htmlAttributes);
public override TagBuilder GenerateLabel(
ViewContext viewContext,
ModelExplorer modelExplorer,
string expression,
string labelText,
object htmlAttributes)
expression = GetLowerCamelCase(expression);
return base.GenerateLabel(viewContext, modelExplorer, expression, labelText, htmlAttributes);
private string GetLowerCamelCase(string text)
if (!string.IsNullOrEmpty(text))
if (char.IsUpper(text[0]))
return char.ToLower(text[0]) + text.Substring(1);
return text;
现在我们有了 CustomHtmlGenerator
类,我们需要在 IoC 容器中注册它来代替 DefaultHtmlGenerator
。我们可以通过以下两行在 Startup.cs 的 ConfigureServices
方法中做到这一点:
//Replace DefaultHtmlGenerator with CustomHtmlGenerator
services.Remove<IHtmlGenerator, DefaultHtmlGenerator>();
services.AddTransient<IHtmlGenerator, CustomHtmlGenerator>();
很酷。我们不仅解决了输入字段上的id
和name
大小写问题,而且通过实现我们自己的自定义IHtmlGenerator
并注册它,我们打开了可以完成各种html 自定义的大门.
我开始真正欣赏围绕 IoC 构建的系统的强大功能,以及带有虚拟方法的默认类。在这种方法下不费吹灰之力就能实现的定制水平非常惊人。
更新
@Gup3rSuR4c 指出我的 services.Remove
调用必须是框架中未包含的扩展方法。我查了一下,是的,确实如此。所以,这里是那个扩展方法的代码:
public static class IServiceCollectionExtensions
public static void Remove<TServiceType, TImplementationType>(this IServiceCollection services)
var serviceDescriptor = services.First(s => s.ServiceType == typeof(TServiceType) &&
s.ImplementationType == typeof(TImplementationType));
services.Remove(serviceDescriptor);
【讨论】:
您的回答让我想到了我需要的东西,即用点替换为 ids 生成的该死的下划线。应该注意的是,您使用的services.Remove<TService, TImplementation>()
不是内置扩展,必须单独创建,或者至少据我所知似乎是这样。
感谢您的评论。好点子。我将使用该服务的代码更新我的答案。删除扩展方法。
用飞机犁地...?这不是“有点”太多的开销吗……?
@MladenB.应该几乎没有开销,只有在需要时将字符串操作小写为单个前导字符的开销。【参考方案2】:
最简单的方法就是写
<input asp-for="StartDate" name="startDate" />
或者你想让它在骆驼情况下完全自动生成,用于整个应用程序?
为此,您似乎必须在 Microsoft.AspNetCore.Mvc.TagHelpers 中实现自己的 InputTagHelpers。
这里是生成名字的方法:
private TagBuilder GenerateTextBox(ModelExplorer modelExplorer, string inputTypeHint, string inputType)
var format = Format;
if (string.IsNullOrEmpty(format))
format = GetFormat(modelExplorer, inputTypeHint, inputType);
var htmlAttributes = new Dictionary<string, object>
"type", inputType
;
if (string.Equals(inputType, "file") && string.Equals(inputTypeHint, TemplateRenderer.IEnumerableOfIFormFileName))
htmlAttributes["multiple"] = "multiple";
return Generator.GenerateTextBox(
ViewContext,
modelExplorer,
For.Name,
value: modelExplorer.Model,
format: format,
htmlAttributes: htmlAttributes);
(以上代码来自https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs, Apache License, Version 2.0, Copyright .NET Foundation)
该行是“For.Name”。该名称被发送到其他一些方法中,最终给出最终名称的是静态类(Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.NameAndIdProvider),所以我们不能轻易插入。
【讨论】:
您的回答启发了我深入研究源代码,我发现可以实现系统范围的方法。我第一次真正开始体会到使用 IoC 容器构建系统的强大功能。 @RonC 这是个好消息 :-)以上是关于如何让 asp-for 输入标签助手生成驼峰命名法名称?的主要内容,如果未能解决你的问题,请参考以下文章