C#到VB.Net HtmlHelper扩展转换错误
我最近将一个HtmlHelper从C#转换为VB.Net,我的razor视图中出现了一个错误。出于某种原因,helper方法在视图中请求htmlhelper参数。我在C#中测试了原始代码,它可以工作,并且不需要第一个参数。代码如下: 原始C#扩展名: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
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 有人有解决办法吗?