You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core6自定义HTML助手委托签名不兼容问题求助

解决ASP.NET MVC自定义HTML助手迁移至.NET Core 6时的委托签名不兼容问题

错误信息:ArgumentException: Cannot bind to the target method because its signature is not compatible with that of the delegate type

问题根源

  • 原代码依赖.NET Framework中System.Web.Mvc.Html.InputExtensions的私有方法InputHelper、CheckBoxHelper等,但这些方法在.NET Core 6的ASP.NET Core MVC中完全不存在——ASP.NET Core MVC是全新重构的框架,内部实现、类型体系与旧版完全不同。
  • 旧版的HtmlHelper(System.Web.Mvc.HtmlHelper)与Core版的IHtmlHelper(Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper)是不同类型,方法签名、参数要求差异极大,导致委托无法绑定。
  • 旧版的MvcHtmlString在Core中已替换为HtmlString,但核心问题还是目标方法不存在。

解决方案

彻底移除对旧版私有方法的反射调用,改用ASP.NET Core MVC原生的公开API实现自定义HTML助手,或者直接构建HTML内容。

重构后的代码示例

using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Html;
using RateChangingSystemCore1.MetadataProviders;
using RateChangingSystemCore1.Models;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace RateChangingSystemCore1.Extensions
{
    public static class EditorExtensions
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private static readonly CoopMetadataProvider _metadataProvider = new CoopMetadataProvider();

        private static ModelMetadata GetDefinitionMetaData(Definition definition)
        {
            if (HttpContextHelper.Current.Items.TryGetValue("definitionMetaDataCache", out var cacheObj) 
                && cacheObj is Dictionary<int, ModelMetadata> definitionMetaDataCache)
            {
                if (definitionMetaDataCache.TryGetValue(definition.NodeID, out var metadata))
                {
                    return metadata;
                }
            }
            else
            {
                var definitionMetaDataCache = new Dictionary<int, ModelMetadata>();
                HttpContextHelper.Current.Items["definitionMetaDataCache"] = definitionMetaDataCache;
            }

            log.DebugFormat("Making meta data for {0}", definition.NodeID);
            // 注意:Core中ModelMetadata的创建方式需调整,确保CoopMetadataProvider适配Core的IModelMetadataProvider接口
            var modelMetadata = _metadataProvider.CreateMetadata2(null, typeof(Definition), () => definition, typeof(Definition), null);
            
            ((Dictionary<int, ModelMetadata>)HttpContextHelper.Current.Items["definitionMetaDataCache"])[definition.NodeID] = modelMetadata;
            return modelMetadata;
        }

        private static HtmlString CoopEditorCommon(this IHtmlHelper html, string name, object value, IDictionary<string, object> htmlAttributes, Definition definition, Func<ModelMetadata, object, HtmlString> inputHelper)
        {
            definition = definition ?? html.ViewData["Definition"] as Definition;
            var modelMetadata = GetDefinitionMetaData(definition);
            
            object formattedModelValue = definition.ValueValue;
            string formatString = modelMetadata.EditFormatString;

            if (modelMetadata.ModelType != null && !string.IsNullOrEmpty(formatString))
            {
                formattedModelValue = string.Format(CultureInfo.CurrentCulture, formatString, definition.ValueValue);
            }

            return inputHelper(modelMetadata, formattedModelValue);
        }

        public static HtmlString CoopTextBox(this IHtmlHelper html, string name, object value, IDictionary<string, object> htmlAttributes)
        {
            return CoopEditorCommon(html, name, value, htmlAttributes, null, (modelMetadata, formattedModelValue) =>
            {
                // 改用Core原生的TextBox方法,或直接构建input元素
                return html.TextBox(name, formattedModelValue, htmlAttributes);
            });
        }

        public static HtmlString CoopTextBox(this IHtmlHelper html, string name, object value, Definition definition, IDictionary<string, object> htmlAttributes)
        {
            return CoopEditorCommon(html, name, value, htmlAttributes, definition, (modelMetadata, formattedModelValue) =>
            {
                return html.TextBox(name, formattedModelValue, htmlAttributes);
            });
        }

        public static HtmlString CoopCheckBoxFor(this IHtmlHelper html, string name, object value, IDictionary<string, object> htmlAttributes)
        {
            return CoopEditorCommon(html, name, value, htmlAttributes, null, (modelMetadata, formattedModelValue) =>
            {
                bool isChecked = formattedModelValue != null && bool.TryParse(formattedModelValue.ToString(), out var result) && result;
                return html.CheckBox(name, isChecked, htmlAttributes);
            });
        }

        public static HtmlString CoopCheckBoxFor(this IHtmlHelper html, string name, object value, Definition definition, IDictionary<string, object> htmlAttributes)
        {
            return CoopEditorCommon(html, name, value, htmlAttributes, definition, (modelMetadata, formattedModelValue) =>
            {
                bool isChecked = formattedModelValue != null && bool.TryParse(formattedModelValue.ToString(), out var result) && result;
                return html.CheckBox(name, isChecked, htmlAttributes);
            });
        }

        public static HtmlString CoopMultiLineBox(this IHtmlHelper html, string name, object value, IDictionary<string, object> htmlAttributes)
        {
            return CoopEditorCommon(html, name, value, htmlAttributes, null, (modelMetadata, formattedModelValue) =>
            {
                return html.TextArea(name, formattedModelValue?.ToString(), htmlAttributes);
            });
        }

        public static HtmlString CoopMultiLineBox(this IHtmlHelper html, string name, object value, Definition definition, IDictionary<string, object> htmlAttributes)
        {
            return CoopEditorCommon(html, name, value, htmlAttributes, definition, (modelMetadata, formattedModelValue) =>
            {
                return html.TextArea(name, formattedModelValue?.ToString(), htmlAttributes);
            });
        }
    }
}

额外注意事项

  • 确保CoopMetadataProvider适配ASP.NET Core的IModelMetadataProvider接口,旧版的CreateMetadata方法签名在Core中已变更,需调整实现。
  • 移除所有对System.Web.Mvc命名空间的引用,替换为Microsoft.AspNetCore.Mvc相关命名空间。
  • HttpContextHelper在Core中需基于IHttpContextAccessor实现,确保能正确获取当前HttpContext。

内容的提问来源于stack exchange,提问作者pooja sankpal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:07:31