ASP.NET MVC中HTML元素的ID生成

14
我需要为ASP.NET MVC应用程序生成HTML元素的唯一标识符。 在经典的ASP.NET中,我可以使用
<a id=<%=ClientID>%>

在ASP.NET MVC世界中是否有类似的解决方案?

更新:

例如,我想创建一个可重用的Button元素。我希望代码看起来类似于

<div class="myButton" id="<%=ClientID%>">
<script>
  var button = document.getElementById(<%=ClientID%>);
  button.onclick = ....
</script>
如果ClientId不可用,那么最好的方法是什么? 目前,我看到两个选项-像Guid.NewGuid()这样生成它或从外部传递id?还有其他选项吗? 更新: 目前,我已经想到了以下解决方案。
    public static string UniqueId(this HtmlHelper html)
    {
        var idGenerator = html.ViewContext.HttpContext.Items[typeof (UniqueIdGenerator)] as UniqueIdGenerator;
        if (idGenerator==null)
            html.ViewContext.HttpContext.Items[typeof (UniqueIdGenerator)] = idGenerator = new UniqueIdGenerator();
        return idGenerator.Next();
    }
       ...
    private class UniqueIdGenerator
    {
        private int id;

        public string Next()
        {
            id++;
            return "_c" + id; // todo: optimize
        }
    }

1
不行,<a id=<%=ClientID>%> 不能生成唯一的ID。 - SLaks
嗨,Alex,你的问题对我来说很有意义,我理解了这个问题,但是我无法回答,因为我也是MVC的新手。不管怎样,你能解释一下为什么需要这个吗?以便如果有人有想法可以得到与你想要做的相同的东西吗? - Davide Piras
3
看起来你非常习惯于使用Web表单的方式来解决问题,但我建议你重新审视一下你的问题,并看看是否可以尝试其他方法,你只需要换一种思考方式。如果你告诉我们你真正的问题,我们或许能够提供更多帮助。但如果你只是想使用ID,可以使用一个随机数字和名称字符串。这就是ID的全部含义,除了命名容器之外,但在MVC中,我们不需要这些。 - Daniel Little
control.ClientID 不会生成 ID,它返回生成的客户端 ID 的值。 - Omu
4个回答

20

使用内置的.NET库中最简单的正确解决方案,无需编写新的自定义应用程序代码

使用Guid.NewGuid(),并采用" N "数字表示法的ToString(),以防止产生浏览器JS问题的无效字符。

Guid.NewGuid().ToString("N");

引用MSDN有关"N"格式说明:

32位数字: 00000000000000000000000000000000

不要使用默认的GUID表示法,因为连字符在JS/jQuery中可能会有问题。

为了完整起见,在GUID开头最好加上一个字母。虽然我在现代浏览器中从未遇到过此类问题,但技术上说,HTML id必须以字母开头而不是数字。


1
很棒的解决方案。这是一个相当琐碎的任务,如果你想要的话,MVC本应该自己处理它。 - Guy Lowe
1
我可以建议您的示例包括alpha前缀吗? $"a{Guid.NewGuid():N}" - Aaron Hudon

1
我喜欢你在更新中提供的答案,比起使用 Guid,因为后者每次都会不同,这使得客户端调试和在视图源中查找元素更加困难。
我进一步添加了自定义的 prefix.. 每个 prefix 都使用自己的计数器,以帮助更进一步。
    public static string GetUniqueHtmlid(this HtmlHelper html, string prefix)
    {
        var generator = html.ViewContext.HttpContext.Items[typeof (UniqueHtmlIdGenerator)] as UniqueHtmlIdGenerator;

        if(generator == null)
            html.ViewContext.HttpContext.Items[typeof(UniqueHtmlIdGenerator)] = generator = new UniqueHtmlIdGenerator();

        return generator.GetNextUniqueId(prefix);
    }

    private class UniqueHtmlIdGenerator
    {
        private readonly Dictionary<string, int> _items = new Dictionary<string, int>();

        public string GetNextUniqueId(string prefix)
        {
            if (string.IsNullOrEmpty(prefix))
                prefix = "item";

            int current;

            lock (typeof (UniqueHtmlIdGenerator))
            {
                current = _items.ContainsKey(prefix) ? _items[prefix] : 1;

                _items[prefix] = current + 1;
            }

            return string.Format("{0}-{1}", prefix, current);
        }
    }

1

这个问题没有单一的解决方案。

您需要修改代码,根据生成元素的内容生成ID。

例如,如果您正在循环遍历数据库中的行,则可以使用行的主键生成ID。

或者,您可以完全放弃使用ID,而使用非唯一类。(这在jQuery和后代选择器中特别方便)


-2
也许这个草稿代码能帮到你:
static class MyIdGenerator
{
    public static int NextID()
    {
        static int _id = 0;
        return _id++;
    }
}

使用静态计数器,每次调用NextID()函数将返回下一个ID;


1
谢谢您的建议,但是像这样的代码如果从多个线程中调用可能会失败。想象一下一个客户端发送两个ajax请求 :) - Alex Ilyin
是的,它的代码不是线程安全的,可能会生成意外的序列。我认为需要重构代码,避免使用生成的ID。在MVC范例中,不需要像这段代码一样使用ID,因为将模型属性映射到ID是错误的。在MVC中,可以使用HTML模板来映射复杂类型和集合 - http://stackoverflow.com/search?q=MVC+collections+in+model - Kuvalda.Spb.Ru
1
正确的线程安全实现如下:静态类 MyIdGenerator { private static int _id; public static int NextId() { return System.Threading.Interlocked.Increment(ref _id); } } - Salvatore Previti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接