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 assign/get a value to a Request to enable this?
Add it to the request item collection odetocode.com/articles/111.aspx
Guid.NewGuid()
Will generate a unique id.
http://msdn.microsoft.com/en-us/library/system.guid.newguid(v=vs.110).aspx
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];
}
}
#Update
@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<TK,TV>
class. Which gives a convenient and memory safe way of tackling this problem:
private static readonly ConditionalWeakTable<object, ConcurrentDictionary<string, object>>
Ephemerons = new ConditionalWeakTable<object, ConcurrentDictionary<string, object>>();
public static Guid GetId(this HttpContext ctx)
{
var dict = Ephemerons.GetOrCreateValue(ctx);
var id = (Guid)dict.GetOrAdd(
"c53fd485-b6b6-4da9-9e9d-bf30500d510b",
_ => Guid.NewGuid());
return id;
}
public static Guid GetId(this HttpContextBase ctx)
{
// this is slow and subject to breaking change; TODO: smart things to mitigate those problems
var innerContext = (HttpContext)ctx.GetType().GetField("_context", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(ctx);
return innerContext.GetId();
}
My Overby.Extensions.Attachments package has an extension method that simplify things.
/// <summary>
/// Unique identifier for the object reference.
/// </summary>
public static Guid GetReferenceId(this object obj) =>
obj.GetOrSetAttached(() => Guid.NewGuid(), RefIdKey);
Using that extension method, you would just call httpContext.GetReferenceId()
.
If you need a single value without having to implement something like Guid.NewGuid()
, perhaps the HttpContext
timestamp will work for you.
int requestId = System.Web.HttpContext.Current.Timestamp.Ticks;
A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond, or 10 million ticks in a second.
Then this solution should be evaluated according to their circumstances because there is the possibility that two requests fall on the same tick of time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With