在研究了@Bebben發佈的代碼和提供的鏈接後,我繼續深入研究了Asp.Net Core源代碼。我發現Asp.Net Core的設計人員提供了一些可擴展點,可以用來實現較低的camelCase 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
類,則需要在地方DefaultHtmlGenerator
的註冊它的IoC容器。我們可以在啓動的ConfigureServices
方法中執行此操作。cs通過以下兩行:
//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);
}
}
你的回答讓我想到了我需要的是用點代替爲id生成的darn下劃線。應該注意的是,你使用的'services.Remove()'不是一個內置的擴展,必須單獨創建,或者至少據我所知,似乎是這樣。 –
Gup3rSuR4c
感謝您的評論。好點子。我將更新我的答案與該服務的代碼.Remove擴展方法。 –