In our MVC 5 site, no session, we need to get/generate a unique ID per request. THhis will be used as an ID for logging all activity in the request.
Is there a way to as
Here's some extension methods that I created for this purpose:
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 made a comment about interned strings not being garbage collected. This is a good point. In a very busy web app that doesn't recycle app pools frequently enough (or ever) this would be a serious issue.
Thankfully, recent versions of .NET have ephemeron support via the ConditionalWeakTable
class. Which gives a convenient and memory safe way of tackling this problem:
private static readonly ConditionalWeakTable
My Overby.Extensions.Attachments package has an extension method that simplify things.
///
/// Unique identifier for the object reference.
///
public static Guid GetReferenceId(this object obj) =>
obj.GetOrSetAttached(() => Guid.NewGuid(), RefIdKey);
Using that extension method, you would just call httpContext.GetReferenceId()
.