MVC Helper,具有相同参数的方法会给出不同的结果
本文关键字:方法 结果 参数 Helper MVC | 更新日期: 2023-09-27 17:58:02
我正在为MVC创建一个助手类,当参数"routeValues"以不同的方式传递时发现了一个问题。创建这些方法是为了在默认情况下定义某些属性。下面的代码是我用来解释我的问题的一个片段
我有一个方法"MyBeginForm()"不接受"routeValues"的参数,"routeVvalues"参数是作为null直接传递给"BeginForm"方法的。另一个方法"MyBeginForm(object routeValues)"接受"routeValue"的一个参数,我通过该参数传递了"null"值。问题是生成的html彼此不同。
//Custom Class for custom attributes
public class MyHtmlHelper<TModel>
{
private readonly HtmlHelper<TModel> htmlHelper;
internal MyHtmlHelper(HtmlHelper<TModel> htmlHelper)
{
this.htmlHelper = htmlHelper;
}
//Here the routeValues parameter of Begin Form is passed directly to the method as null
public MvcForm MyBeginForm()
{
var myAttributes = new Dictionary<string, object>(){
{"test", "value"},
{"test2", "value2"},
};
return htmlHelper.BeginForm("Index", "Home", null, FormMethod.Post, myAttributes);
}
//Here I have passed the null value through the parameter
public MvcForm MyBeginForm(object routeValues)
{
var myAttributes = new Dictionary<string, object>(){
{"test", "value"},
{"test2", "value2"},
};
return htmlHelper.BeginForm("Index", "Home", routeValues, FormMethod.Post, myAttributes);
}
}
//This class is used for static call in html
public static class MyHtmlHelperkEx
{
public static MyHtmlHelper<TModel> MyHtmlHelper<TModel>(this HtmlHelper<TModel> htmlHelper)
{
return new MyHtmlHelper<TModel>(htmlHelper);
}
}
以下代码段用于html端
<h1>Without Parameter</h1>
@using (Html.MyHtmlHelper().MyBeginForm()) { }
<h1>With parmeter</h1>
@using (Html.MyHtmlHelper().MyBeginForm(null)) { }
下面是生成的html。您可以看到属性的生成方式不同。
<h1>Without Parameter</h1>
<form action="/" method="post" test="value" test2="value2">
System.Web.Mvc.Html.MvcForm
</form>
<h1>With parmeter</h1>
<form comparer="System.Collections.Generic.GenericEqualityComparer`1[System.String]" count="2" keys="System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.Object]" values="System.Collections.Generic.Dictionary`2+ValueCollection[System.String,System.Object]" action="/" method="post"></form>
有人能解释一下为什么会发生这种情况,以及我如何解决它吗。
您正在混合routeValues和htmlAttributes参数的类型。
BeginForm
有2个过载,需要5个参数:
-
其中routeValues和htmlAttributes都声明为匿名对象。参见msdn
-
另一个routeValues类型为
RouteValueDictionary
且htmlAttributes的类型为IDictionary<string, Object>
。看见msdn
然而,在您的助手中,您混合了类型。htmlAttributes被声明为字典,routeValues被声明为对象。
没有参数的MyBeginForm
重载之所以有效,是因为您将null作为routeValues参数传递,因此编译器使用其他参数的类型来决定应该使用哪个BeginForm
重载。由于htmlAttributes是一个字典,它将使用我上面描述的第二个重载。你可以很快尝试改变你的方法,将null routeValues强制为type object,这将迫使错误的重载成为picker,你会得到同样意外的html:
return htmlHelper.BeginForm("Index", "Home", (object)null, FormMethod.Post, myAttributes);
同样,你的第二个MyBeginForm
重载并没有像你预期的那样工作,因为你已经声明了object类型的routeValues,所以编译器总是会得到我上面提到的第一个重载(其中routeValue和htmlAttributes都被视为匿名对象)。
现在你知道发生了什么,你只需要确保你选择了正确的过载来解决你的问题。我会修复允许指定routeValues的MyBeginForm
重载,然后更新不带参数的重载来调用这个重载(避免重复代码)。
修复它的最简单方法是将方法中的htmlAttributes定义为匿名对象:
public MvcForm MyBeginForm(object routeValues)
{
var myAttributes = new{
test = "value",
test2 = "value2",
};
return htmlHelper.BeginForm("Index", "Home", routeValues, FormMethod.Post, myAttributes);
}
另一个选项是将routeValues参数声明为RouteValuesDictionary,这样您就可以继续将htmlAttributes定义为字典。
public MvcForm MyBeginForm(RouteValueDictionary routeValues)
{
var myAttributes = new Dictionary<string, object>(){
{"test", "value"},
{"test2", "value2"},
};
return htmlHelper.BeginForm("Index", "Home", routeValues, FormMethod.Post, myAttributes);
}
在这两种情况下,调用传递null作为参数的助手将呈现预期的html(尽管我更喜欢使用routeValues作为匿名对象):
<form action="/" method="post" test="value" test2="value2"></form>
然后你可以像这样更新你的助手的第一个过载:
public MvcForm MyBeginForm()
{
return MyBeginForm(null);
}
现在MyBeginForm
的两个重载都应该如您所期望的那样工作。
希望它能有所帮助!