【问题标题】:Asp.Net MVC Unique id per requestAsp.Net MVC 每个请求的唯一 ID
【发布时间】:2014-10-09 21:51:07
【问题描述】:

在我们的 MVC 5 站点中,没有会话,我们需要为每个请求获取/生成唯一 ID。这将用作记录请求中所有活动的 ID。

有没有办法为请求分配/获取值以启用此功能?

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-5


【解决方案1】:

将其添加到请求项集合 odetocode.com/articles/111.aspx

Guid.NewGuid()

会生成一个唯一的id。

http://msdn.microsoft.com/en-us/library/system.guid.newguid(v=vs.110).aspx

【讨论】:

  • 但是如何将它附加到请求中,以便在请求的整个生命周期中都可以访问它。
【解决方案2】:

这是我为此目的创建的一些扩展方法:

public static Guid GetId(this HttpContext ctx) => new HttpContextWrapper(ctx).GetId();

public static Guid GetId(this HttpContextBase ctx)
{
    const string key = "tq8OuyxHpDgkRg54klfpqg== (Request Id Key)";

    if (ctx.Items.Contains(key))
        return (Guid) ctx.Items[key];

    var mutex = string.Intern($"{key}:{ctx.GetHashCode()}");
    lock (mutex)
    {
        if (!ctx.Items.Contains(key))
            ctx.Items[key] = Guid.NewGuid();

        return (Guid) ctx.Items[key];
    }
}

更新

@Luiso 评论了没有被垃圾收集的实习字符串。这是个好的观点。在一个非常繁忙的网络应用程序中,没有足够频繁(或永远)回收应用程序池,这将是一个严重的问题。

谢天谢地,最新版本的 .NET 通过 ConditionalWeakTable<TK,TV> 类支持 ephemeron。这为解决此问题提供了一种方便且内存安全的方法:

private static readonly ConditionalWeakTable<object, ConcurrentDictionary<string, object>>
Ephemerons = new ConditionalWeakTable<object, ConcurrentDictionary<string, object>>();

public static Guid GetId(this HttpContext ctx) => new HttpContextWrapper(ctx).GetId();

public static Guid GetId(this HttpContextBase ctx)
{
    var dict = Ephemerons.GetOrCreateValue(ctx);
    var id = (Guid)dict.GetOrAdd(
        "c53fd485-b6b6-4da9-9e9d-bf30500d510b",
        _ => Guid.NewGuid());
    return id;
}

我的Overby.Extensions.Attachments 包有一个可以简化事情的扩展方法。

/// <summary>
/// Unique identifier for the object reference.
/// </summary>
public static Guid GetReferenceId(this object obj) =>
    obj.GetOrSetAttached(() => Guid.NewGuid(), RefIdKey);

使用该扩展方法,您只需调用httpContext.GetReferenceId()

【讨论】:

  • 你为什么在这里使用string.Intern作为互斥锁?
  • 因为它产生了一个我不必跟踪的对象引用。我在这里谈论更多:stackoverflow.com/a/29878495/64334
  • @RonnieOverby 不会实习这么多字符串(每个请求一个)会对内存使用产生负面影响,因为实习字符串不会被垃圾收集并且会保留在池中直到重新启动?跨度>
【解决方案3】:

如果您需要单个值而无需实现类似Guid.NewGuid() 的东西,那么HttpContext 时间戳可能适合您。

int requestId = System.Web.HttpContext.Current.Timestamp.Ticks;

单个滴答表示一百纳秒或百万分之一秒。一毫秒有 10,000 个滴答声,或一秒有 1000 万个滴答声。

那么这个解决方案应该根据他们的情况来评估,因为有可能两个请求落在同一个时间点上。

【讨论】:

    猜你喜欢
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多