2016-02-29 8 views
5

Ich habe folgendes ein:C# Wie auf einem Cookie übergeben mit einem gemeinsamen Httpclient

JS-Client -> Web-Api -> Web-Api

Ich brauche unten Auth Cookie den ganzen Weg zu schicken . Mein Problem ist, es von einer Web-API in eine andere zu schicken. Aufgrund der Integration in ein älteres System, das FormsAuthentication verwendet, muss ich das Authentifizierungs-Cookie weitergeben.

Aus Performance-Gründen teile ich eine Liste von HttpClients (eine für jede Web-api) im folgenden Wörterbuch:

private static ConcurrentDictionary<ApiIdentifier, HttpClient> _clients = new ConcurrentDictionary<ApiIdentifier, HttpClient>(); 

So eine Kennung I die entsprechende Httpclient greifen kann.

Folgende Arbeiten, aber ich bin mir ziemlich sicher, dass dieser schlechter Code ist:

HttpClient client = _clients[identifier]; 
var callerRequest = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage; 
string authCookieValue = GetAuthCookieValue(callerRequest); 

if (authCookieValue != null) 
{ 
    client.DefaultRequestHeaders.Remove("Cookie"); 
    client.DefaultRequestHeaders.Add("Cookie", ".ASPXAUTH=" + authCookieValue); 
} 

HttpResponseMessage response = await client.PutAsJsonAsync(methodName, dataToSend); 

// Handle response... 

Was ist falsch daran ist, dass 1) es falsch scheint DefaultRequestHeaders in einer Anfrage zu manipulieren und 2) potenziell zwei simultanious Anfragen kann die Cookies durcheinander bringen, da der HttpClient geteilt wird.

Ich habe eine Weile gesucht, ohne eine Lösung zu finden, da die meisten mit einem passenden Problem den HttpClient für jede Anfrage instanziiert, so dass die erforderlichen Header gesetzt werden können, die ich vermeiden möchte.

An einem Punkt hatte ich Anfragen erhalten arbeiten mit einem HttpResponseMessage. Vielleicht kann das eine Lösung sein.

Also meine Frage ist: Gibt es eine Möglichkeit, Cookies für eine einzelne Anfrage mit einem HttpClient, die von anderen Clients mit der gleichen Instanz sicher ist, zu setzen?

Antwort

11

Statt PutAsJsonAsync von() aufrufen, können Sie verwenden HttpRequestMessage und SendAsync():

Uri requestUri = ...; 
HttpMethod method = HttpMethod.Get /*Put, Post, Delete, etc.*/; 
var request = new HttpRequestMessage(method, requestUri); 
request.Headers.TryAddWithoutValidation("Cookie", ".ASPXAUTH=" + authCookieValue); 
request.Content = new StringContent(jsonDataToSend, Encoding.UTF8, "application/json"); 
var response = await client.SendAsync(request); 

UPDATE: Um sicherzustellen, dass Ihre HTTP-Client speichert keine Cookies von einer Antwort müssen Sie dies tun:

Andernfalls können Sie unerwartetes Verhalten erhalten, wenn Sie einen Client verwenden und andere Cookies freigeben.

+0

Vielen Dank! Ich war wirklich nah dran, aber du hast es über die Ziellinie geschafft. Eine Frage: Ist es möglich eine GET-Anfrage zu haben, benutze auch den stringcontent? Wenn mein 'jsonDataToSend' ein komplexes Objekt ist, wird es nicht weitergegeben, aber wenn ich es selbst in einen Querystring umwandle und es als 'Methode' übergebe, funktioniert es. Wäre schön, eine generische Methode zu haben :) – Casper

+0

np :) Normalerweise enthält GET keine Körper, aber es ist nicht durch die Spezifikation verboten. Sie können 'new ObjectContent (Wert, new JsonMediaTypeFormatter()," application/json ")' 'anstelle von' StringContent' verwenden –

Verwandte Themen