2014-10-09 11 views
7

Nel nostro sito MVC 5, nessuna sessione, è necessario ottenere/generare un ID univoco per richiesta. Questo verrà utilizzato come ID per registrare tutte le attività nella richiesta.Asp.Net MVC ID univoco per richiesta

C'è un modo per assegnare/ottenere un valore a una richiesta per abilitare questo?

+0

Possibile duplicato di [ID richiesta univoco di log4net in ASP.NET] (http://stackoverflow.com/questions/15842321/log4net-unique-request-id-in-asp-net) –

risposta

8

Aggiungere alla raccolta di articolo di richiesta odetocode.com/articles/111.aspx~~V~~3rd

Guid.NewGuid() 

Genererà un ID univoco.

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

+1

Ma come lo ho allegato a una richiesta in modo che sia accessibile nell'intero ciclo di vita della richiesta. –

+3

Aggiungilo alla raccolta di elementi della richiesta http://odetocode.com/articles/111.aspx – TGH

6

Ecco alcuni metodi di estensione che ho creato per questo scopo:

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]; 
    } 
} 

Aggiornamento

@Luiso fatto un commento su stringhe internati non essere garbage collection. Questo è un buon punto. In un'app web molto impegnativa che non ricicla abbastanza frequentemente (o mai) i pool di app questo sarebbe un problema serio.

Fortunatamente, le versioni recenti di .NET dispongono del supporto effimero tramite la classe ConditionalWeakTable<TK,TV>. Che dà un modo sicuro e conveniente la memoria di affrontare questo problema:

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; 
} 

Il mio pacchetto Overby.Extensions.Attachments ha un metodo di estensione che semplificare le cose.

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

Utilizzando questo metodo di estensione, si sarebbe solo chiamare httpContext.GetReferenceId().

+0

perché stai utilizzando 'string.Intern' per il mutex qui? – robbymurphy

+0

Perché produce riferimenti a oggetti di cui non devo tenere traccia. Ne parlo di più qui: http://stackoverflow.com/a/29878495/64334 –

+0

Perché il downvote? –