asp.net-mvc - 如何重写 Html.ActionLink?

标签 asp.net-mvc

我通常希望使用数据库中的内容呈现 ActionLink(想象一个 Id/Name 组合),因此我会将以下内容放入我的 View 中:

        @foreach (var row in Model)
        {
            <li>@Html.ActionLink(row.Name, "Action", "Controller", new { id = row.Id })</li>
        }

但是,如果名称为空字符串,则会引发异常。有什么办法可以防止这种情况发生吗?我想覆盖 ActionLink,但它是一个扩展,所以我无法覆盖。

有什么建议吗?

编辑:

首先,我不控制数据,否则我会确保“名称”字段是必填字段并且始终填充。不幸的是,这种情况并非如此。

其次,我意识到用户将没有任何可点击的内容,但我相信呈现空链接是比给他们 YSOD 更好的选择。

最佳答案

事实证明,实例方法始终优于具有相同签名的扩展方法。

我能够加载 CustomHtmlHelper 并将实例方法 ActionLink 方法放入新类中:

public abstract class CustomWebViewPage<T> : WebViewPage<T>
{
    public new CustomHtmlHelper<T> Html { get; set; }

    public override void InitHelpers()
    {
        Ajax = new AjaxHelper<T>(ViewContext, this);
        Url = new UrlHelper(ViewContext.RequestContext);

        //Load Custom Html Helper instead of Default
        Html = new CustomHtmlHelper<T>(ViewContext, this);
    }
}

HtmlHelper 如下(从 Reflector 复制的 ActionLink 方法,没有进行 LinkText 错误检查:

public class CustomHtmlHelper<T> : HtmlHelper<T>
{
    public CustomHtmlHelper(ViewContext viewContext, IViewDataContainer viewDataContainer) :
        base(viewContext, viewDataContainer)
    {
    }

    //Instance methods will always be called instead of extension methods when both exist with the same signature...

    public MvcHtmlString ActionLink(string linkText, string actionName)
    {
        return ActionLink(linkText, actionName, null, new RouteValueDictionary(), new RouteValueDictionary());
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, object routeValues)
    {
        return ActionLink(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary());
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, string controllerName)
    {
        return ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary());
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, RouteValueDictionary routeValues)
    {
        return ActionLink(linkText, actionName, null, routeValues, new RouteValueDictionary());
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, object routeValues, object htmlAttributes)
    {
        return ActionLink(linkText, actionName, null, new RouteValueDictionary(routeValues), AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        return ActionLink(linkText, actionName, null, routeValues, htmlAttributes);
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        return ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(routeValues), AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        return MvcHtmlString.Create(GenerateLink(ViewContext.RequestContext, RouteCollection, linkText, null, actionName, controllerName, routeValues, htmlAttributes));
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes)
    {
        return ActionLink(linkText, actionName, controllerName, protocol, hostName, fragment, new RouteValueDictionary(routeValues), AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public MvcHtmlString ActionLink(string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        return MvcHtmlString.Create(GenerateLink(ViewContext.RequestContext, RouteCollection, linkText, null, actionName, controllerName, protocol, hostName, fragment, routeValues, htmlAttributes));
    }
}

最后,将 pageBaseType 设置为 Views/Web.config 文件以使用新的自定义 WebViewPage:

  <system.web.webPages.razor>
    ...
    <pages pageBaseType="Fully.Qualified.Namespace.CustomWebViewPage">
    ...
    </pages>
  </system.web.webPages.razor>

希望这对其他人有帮助。

关于asp.net-mvc - 如何重写 Html.ActionLink?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15952240/

相关文章:

c# - EF 6 关系 : One or more validation errors were detected during model generation

asp.net - 使用 JQuery 渲染部分 View 时遇到问题

c# - 来自内部调用的函数的输出字符串 @{}

javascript - 在强类型 View 中渲染 Ajax 接收到的数据

asp.net - 在 MVC 中使用 MEF 实现可插拔架构

asp.net - session 过期事件?

asp.net - 使用 WebAPI 时重新验证模型(TryValidateModel 等效项)

asp.net-mvc - 如何使用可空类型的强类型 HTML 助手?

c# - jQuery ajax - 通过 GET 传递多个参数

asp.net-mvc - 管理 Ajax session 超时