C# 如何重载MVC HtmlHelper扩展方法
我正在尝试注册一个自定义MVC HtmlHelper扩展 我已经为扩展方法创建了相应的静态类和静态方法,但是如何在视图中注册/导入/使用该名称空间,以便它显示为某个给定方法的扩展方法,例如C# 如何重载MVC HtmlHelper扩展方法,c#,asp.net,asp.net-mvc,asp.net-mvc-5,C#,Asp.net,Asp.net Mvc,Asp.net Mvc 5,我正在尝试注册一个自定义MVC HtmlHelper扩展 我已经为扩展方法创建了相应的静态类和静态方法,但是如何在视图中注册/导入/使用该名称空间,以便它显示为某个给定方法的扩展方法,例如@Html.SomeMethod 在Asp.Net WebForms中,我可以简单地添加: <%@ Import Namespace="MyExtensionNamespace.MyExtensionClassName" %> 但是VS告诉我,我的调用下仍然有一个错误,表示无法推断类型参数: 以
@Html.SomeMethod
在Asp.Net WebForms中,我可以简单地添加:
<%@ Import Namespace="MyExtensionNamespace.MyExtensionClassName" %>
但是VS告诉我,我的调用下仍然有一个错误,表示无法推断类型参数:
以下是我的分机代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Reflection;
using System.Linq.Expressions;
namespace EFWCF.Extensions
{
public static class LabelExtensions
{
public static MvcHtmlString LabelFor<PropertyInfo, TValue>(this HtmlHelper<PropertyInfo> html, Expression<Func<PropertyInfo, TValue>> expression)
{
var type = expression.Type;
MvcHtmlString result = new MvcHtmlString(type.FullName);
return result;
}
}
}
但是我希望能够为其他类型调用现有的@Html方法。您可以通过以下两种方式引用名称空间: 直接在视图中:
@using YourProject.HtmlHelpers;
或者,您可以在视图/web.config
文件中添加对该命名空间的引用,这样就不需要使用将添加到视图的顶部:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<!-- Reference here -->
<add namespace="YourProject.HtmlHelpers" />
</namespaces>
</pages>
</system.web.webPages.razor>
无法从用法中推断类型参数,这意味着在将标识符指定为方法类型参数期间发生了泛型类型不匹配。这里,您的自定义扩展方法将System.Reflection.PropertyInfo
定义为TModel
的替代:
public static MvcHtmlString LabelFor<PropertyInfo, TValue>(this HtmlHelper<PropertyInfo> html, Expression<Func<PropertyInfo, TValue>> expression)
{
var type = expression.Type;
MvcHtmlString result = new MvcHtmlString(type.FullName);
return result;
}
根据我的观察,Razor似乎使用HtmlHelper.LabelFor
而不是使用其自定义扩展方法重载,因此在视图页面中,您试图将PropertyInfo
指定为标准LabelFor
上的expression
参数,该参数需要lambda表达式,从而导致CS0411错误
要解决此问题,请将自定义扩展方法名称更改为另一个有效名称(避免命名冲突),或通过对System.Reflection.PropertyInfo
进行类型检查,为标准LabelFor
创建重载,如下例所示:
// note that you still require to insert PropertyInfo as a lambda expression here
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
var modelType = typeof(TModel);
var propertyInfo = typeof(System.Reflection.PropertyInfo);
if (modelType.IsAssignableFrom(propertyInfo))
{
var type = expression.Type;
var tag = new TagHelper("label");
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
tag.MergeAttributes(attributes);
tag.SetInnerText(type.FullName); // set inner text between label tag
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
else
{
// return another value, e.g. return MvcHtmlString.Empty
}
}
然后,在视图
目录中的web.config中引用您的助手名称空间,这样您就不需要在视图页面中使用@using
指令:
<system.web.webPages.razor>
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.UI.WebControls" />
...
<add namespace="EFWCF.Extensions.LabelExtensions" /> <-- add this line
</namespaces>
</pages>
</system.web.webPages.razor>
在Razor中,您可以使用MyExtensionNamespace.MyExtensionClassName使用。请注意,您的扩展方法需要是静态的MvcHtmlString
方法。是的,让我试试。不行,我会更新我的问题。使用EFWCF.Extensions.LabelExtensions在图片中的@红色下划线上会出现什么错误文本?谢谢@TetsuyaYamamoto First error First fixed,正在使用Namespace.ClassName
,而导入时它应该是Namespace
+我同意你的回答。但我再次更新了这个问题。无法推断其投诉类型,应显式定义。感谢提供信息。奇怪的是我的web.config甚至没有这个部分。我目前正在使用第一种方法,但我似乎无法过载。@AlexanderHiggins它是web.config。在视图中,Folder不知道这一点。好消息。至于潜在的问题,我现在明白我无法完成我所尝试的。很棒的更新。我知道您可以在文件夹级别添加.config
文件,但不知道MVC
这样注册了导入。是的,您可以在视图文件夹中使用webconfig…:)。非常感谢@Nkosi指出这一点。快乐分享。:)
public static MvcHtmlString LabelFor<PropertyInfo, TValue>(this HtmlHelper<PropertyInfo> html, Expression<Func<PropertyInfo, TValue>> expression)
{
var type = expression.Type;
MvcHtmlString result = new MvcHtmlString(type.FullName);
return result;
}
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
...
}
// note that you still require to insert PropertyInfo as a lambda expression here
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
var modelType = typeof(TModel);
var propertyInfo = typeof(System.Reflection.PropertyInfo);
if (modelType.IsAssignableFrom(propertyInfo))
{
var type = expression.Type;
var tag = new TagHelper("label");
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
tag.MergeAttributes(attributes);
tag.SetInnerText(type.FullName); // set inner text between label tag
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
else
{
// return another value, e.g. return MvcHtmlString.Empty
}
}
public static MvcHtmlString PropertyLabelFor<TModel>(this HtmlHelper<TModel> html, PropertyInfo propertyInfo, object htmlAttributes)
{
var type = propertyInfo.GetType();
var tag = new TagHelper("label");
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
tag.MergeAttributes(attributes);
tag.SetInnerText(type.FullName); // set inner text between label tag
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
<system.web.webPages.razor>
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.UI.WebControls" />
...
<add namespace="EFWCF.Extensions.LabelExtensions" /> <-- add this line
</namespaces>
</pages>
</system.web.webPages.razor>