C#到VB.Net HtmlHelper扩展转换错误

C#到VB.Net HtmlHelper扩展转换错误,vb.net,Vb.net,我最近将一个HtmlHelper从C#转换为VB.Net,我的razor视图中出现了一个错误。出于某种原因,helper方法在视图中请求htmlhelper参数。我在C#中测试了原始代码,它可以工作,并且不需要第一个参数。代码如下: 原始C#扩展名: namespace MyNamespace { public class ExtendedSelectListItem : SelectListItem { public object htmlAttributes

我最近将一个HtmlHelper从C#转换为VB.Net,我的razor视图中出现了一个错误。出于某种原因,helper方法在视图中请求htmlhelper参数。我在C#中测试了原始代码,它可以工作,并且不需要第一个参数。代码如下:

原始C#扩展名:

namespace MyNamespace
{
    public class ExtendedSelectListItem : SelectListItem
    {
        public object htmlAttributes { get; set; }
    }

    public static partial class HtmlHelperExtensions
    {
        static object GetModelStateValue(HtmlHelper htmlHelper, string key, Type destinationType)
        {
            ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(key, out modelState))
            {
                if (modelState.Value != null)
                {
                    return modelState.Value.ConvertTo(destinationType, null /* culture */);
                }
            }
            return null;
        }

        public static MvcHtmlString ExtendedDropDownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            IEnumerable<ExtendedSelectListItem> selectList,
            string optionLabel,
            object htmlAttributes,
            object selectedValue)
        {
            return SelectInternal(
                htmlHelper,
                optionLabel,
                ExpressionHelper.GetExpressionText(expression),
                selectList,
                false /* allowMultiple */,
                HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),
                selectedValue);
        }

        private static MvcHtmlString SelectInternal(
            this HtmlHelper htmlHelper,
            string optionLabel,
            string name,
            IEnumerable<ExtendedSelectListItem> selectList,
            bool allowMultiple,
            IDictionary<string, object> htmlAttributes,
            object selectedValue)
        {
            string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            if (String.IsNullOrEmpty(fullName))
                throw new ArgumentException("No name");

            if (selectList == null)
                throw new ArgumentException("No selectlist");

            object defaultValue = (allowMultiple) ? GetModelStateValue(htmlHelper, fullName, typeof(string[])) : GetModelStateValue(htmlHelper, fullName, typeof(string));

            // If we haven't already used ViewData to get the entire list of items then we need to
            // use the ViewData-supplied value before using the parameter-supplied value.
            if (defaultValue == null)
                defaultValue = htmlHelper.ViewData.Eval(fullName);

            // If we still don't have the value, use what was passed in
            if (defaultValue == null)
                defaultValue = selectedValue;

            if (defaultValue != null)
            {
                IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
                IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture);
                HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
                List<ExtendedSelectListItem> newSelectList = new List<ExtendedSelectListItem>();

                foreach (ExtendedSelectListItem item in selectList)
                {
                    item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
                    newSelectList.Add(item);
                }
                selectList = newSelectList;
            }
            else
            {
                selectList.Where(li => li.Selected).ToList().ForEach(li => li.Selected = false);
            }

            // Convert each ListItem to an <option> tag
            StringBuilder listItemBuilder = new StringBuilder();

            // Make optionLabel the first item that gets rendered.
            if (optionLabel != null)
                listItemBuilder.Append(ListItemToOption(new ExtendedSelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false }));

            foreach (ExtendedSelectListItem item in selectList)
            {
                listItemBuilder.Append(ListItemToOption(item));
            }

            TagBuilder tagBuilder = new TagBuilder("select")
            {
                InnerHtml = listItemBuilder.ToString()
            };
            tagBuilder.MergeAttributes(htmlAttributes);
            tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
            tagBuilder.GenerateId(fullName);
            if (allowMultiple)
                tagBuilder.MergeAttribute("multiple", "multiple");

            // If there are any errors for a named field, we add the css attribute.
            ModelState modelState;
            if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
            {
                if (modelState.Errors.Count > 0)
                {
                    tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
                }
            }

            tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name));

            return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
        }

        internal static string ListItemToOption(ExtendedSelectListItem item)
        {
            TagBuilder builder = new TagBuilder("option")
            {
                InnerHtml = HttpUtility.HtmlEncode(item.Text)
            };
            if (item.Value != null)
            {
                builder.Attributes["value"] = item.Value;
            }
            if (item.Selected)
            {
                builder.Attributes["selected"] = "selected";
            }
            builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.htmlAttributes));
            return builder.ToString(TagRenderMode.Normal);
        }
    }

}
Namespace MyNamespace

    Public Module HtmlHelperExtensions
        Sub New()
        End Sub

        <System.Runtime.CompilerServices.Extension()> _
        Public Function ExtendedDropDownListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper, expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of ExtendedSelectListItem), optionLabel As String, htmlAttributes As Object, selectedValue As Object) As MvcHtmlString
            ' allowMultiple 
            Return SelectInternal(htmlHelper, optionLabel, ExpressionHelper.GetExpressionText(expression), selectList, False, htmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), selectedValue)
        End Function

        <System.Runtime.CompilerServices.Extension()> _
        Private Function SelectInternal(htmlHelper As HtmlHelper, optionLabel As String, name As String, selectList As IEnumerable(Of ExtendedSelectListItem), allowMultiple As Boolean, htmlAttributes As IDictionary(Of String, Object), selectedValue As Object) As MvcHtmlString
            Dim fullName As String = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name)
            If [String].IsNullOrEmpty(fullName) Then
                Throw New ArgumentException("No name")
            End If

            If selectList Is Nothing Then
                Throw New ArgumentException("No selectlist")
            End If

            Dim defaultValue As Object = If((allowMultiple), GetModelStateValue(htmlHelper, fullName, GetType(String())), GetModelStateValue(htmlHelper, fullName, GetType(String)))

            ' If we haven't already used ViewData to get the entire list of items then we need to
            ' use the ViewData-supplied value before using the parameter-supplied value.
            If defaultValue Is Nothing Then
                defaultValue = htmlHelper.ViewData.Eval(fullName)
            End If

            ' If we still don't have the value, use what was passed in
            If defaultValue Is Nothing Then
                defaultValue = selectedValue
            End If

            If defaultValue IsNot Nothing Then
                Dim defaultValues As IEnumerable = If((allowMultiple), TryCast(defaultValue, IEnumerable), New Object() {defaultValue})
                Dim values As IEnumerable(Of String) = From value In defaultValues Select Convert.ToString(value, CultureInfo.CurrentCulture)
                Dim selectedValues As New HashSet(Of String)(values, StringComparer.OrdinalIgnoreCase)
                Dim newSelectList As New List(Of ExtendedSelectListItem)()

                For Each item As ExtendedSelectListItem In selectList
                    item.Selected = If((item.Value IsNot Nothing), selectedValues.Contains(item.Value), selectedValues.Contains(item.Text))
                    newSelectList.Add(item)
                Next
                selectList = newSelectList
            Else
                selectList.Where(Function(li) li.Selected).ToList().ForEach(Function(li) InlineAssignHelper(li.Selected, False))
            End If

            ' Convert each ListItem to an <option> tag
            Dim listItemBuilder As New StringBuilder()

            ' Make optionLabel the first item that gets rendered.
            If optionLabel IsNot Nothing Then
                listItemBuilder.Append(ListItemToOption(New ExtendedSelectListItem() With { _
                 .Text = optionLabel, _
                 .Value = [String].Empty, _
                 .Selected = False _
                }))
            End If

            For Each item As ExtendedSelectListItem In selectList
                listItemBuilder.Append(ListItemToOption(item))
            Next

            Dim tagBuilder As New TagBuilder("select") With { _
             .InnerHtml = listItemBuilder.ToString() _
            }
            tagBuilder.MergeAttributes(htmlAttributes)
            ' replaceExisting 
            tagBuilder.MergeAttribute("name", fullName, True)
            tagBuilder.GenerateId(fullName)
            If allowMultiple Then
                tagBuilder.MergeAttribute("multiple", "multiple")
            End If

            ' If there are any errors for a named field, we add the css attribute.
            Dim modelState As ModelState = New ModelState()
            If htmlHelper.ViewData.ModelState.TryGetValue(fullName, modelState) Then
                If modelState.Errors.Count > 0 Then
                    tagBuilder.AddCssClass(htmlHelper.ValidationInputCssClassName)
                End If
            End If

            tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name))

            Return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal))
        End Function

        Friend Function GetModelStateValue(htmlHelper As HtmlHelper, key As String, destinationType As Type) As Object
            Dim modelState As ModelState = New ModelState()
            If htmlHelper.ViewData.ModelState.TryGetValue(key, modelState) Then
                If modelState.Value IsNot Nothing Then
                    ' culture 
                    Return modelState.Value.ConvertTo(destinationType, Nothing)
                End If
            End If
            Return Nothing
        End Function

        Friend Function ListItemToOption(item As ExtendedSelectListItem) As String
            Dim builder As New TagBuilder("option") With { _
             .InnerHtml = HttpUtility.HtmlEncode(item.Text) _
            }
            If item.Value IsNot Nothing Then
                builder.Attributes("value") = item.Value
            End If
            If item.Selected Then
                builder.Attributes("selected") = "selected"
            End If
            builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.htmlAttributes))
            Return builder.ToString(TagRenderMode.Normal)
        End Function
        Private Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function


    End Module

End Namespace
@Html.ExtendedDropDownListFor(p => p.filter1.propName, (IEnumerable<ExtendedSelectListItem>)ViewBag.propNames, "", new { @class = "filter1" },null)
@Imports MyNamespace

@HtmlHelperExtensions.ExtendedDropDownListFor(Function(p) p.filter5.propName, CType(ViewBag.propNames, IEnumerable(Of ExtendedSelectListItem)), "", New With {.class = "filter5"}, Nothing)
由于扩展方法需要HtmlHelper参数,因此出现以下错误:

未为“公共函数ExtendedDropDownListFor…”的参数“selectedValue”指定参数


如果您能为我解决这个问题提供任何帮助,我将不胜感激。

在这个问题上也浪费了大约一个小时。在vb.net中,需要将第一个参数htmlHelper传入扩展方法。在C#中,你没有

@RequiredLabelFor(Me.Html,函数(x)x.EmployeeID)


Grrr vb.net

有人有解决办法吗?