Warum kann ich nicht Lesen Http-Request-Eingabe-stream doppelt?
Ich war putting in einige debugging-code zu testen, einige Dinge, und dann wird der debug-code sich nicht so Verhalten wie erwartet. Das nachfolgende Beispiel zeigt einen vereinfachten code zu demonstrieren, meine Frage.
Dies ist in .NET 4 und mit WebApi, ich versuche, drucken Sie den body der http-Anfrage in der debug-code. Um dies zu tun, die ich Suche, der Eingabe-stream zurück und Lesen Sie den stream. Es funktioniert gut, beim ersten mal, aber wenn ich versuchen, es erneut zu Lesen, bekomme ich einen leeren string.
Warum kann ich nicht versuchen Sie zurück und Lesen Sie den InputStream ein zweites mal? Im Beispiel unten, body2 ist immer leer. Im zweiten Satz, CanSeek ist immer noch wahr und der zweite Aufruf ReadToEnd() einen leeren string zurück und überschreiben Sie die Standardeinstellung.
using System.IO;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
public class TestController : ApiController
{
public class TestOutuput
{
public string firstRead;
public string secondRead;
}
public HttpResponseMessage Post()
{
string body1 = "default for one";
string body2 = "default for two";
if (HttpContext.Current.Request.InputStream.CanSeek)
{
HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
}
using (var reader = new StreamReader(HttpContext.Current.Request.InputStream))
{
body1 = reader.ReadToEnd();
}
if (HttpContext.Current.Request.InputStream.CanSeek)
{
HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
}
using (var reader2 = new StreamReader(HttpContext.Current.Request.InputStream))
{
//this is always empty, even after seek back to origin
body2 = reader2.ReadToEnd();
}
TestOutuput testOutput = new TestOutuput() { firstRead = body1, secondRead = body2 };
HttpResponseMessage response = new HttpResponseMessage();
return Request.CreateResponse<TestOutuput>(HttpStatusCode.OK, testOutput);
}
}
CanSeek
zurück true
? Du bist derzeit bedingt zu suchen, sondern dann unter der Annahme, dass das suchen funktioniert hat. Warum sind Sie noch dabei? Ich persönlich würde erwarten, dass zumindest für die große Anfrage Gremien der stream kann nicht im Arbeitsspeicher gepuffert werden. Wenn Sie möchten, erstellen Sie eine Kopie, ich schlage vor, Sie tun, die erste und Lesen Sie dann mehrere Male von Ihrer Kopie. Verwenden Stream.CopyTo in Verbindung mit einem MemoryStream.Ja, CanSeek nicht true zurück und die ReadToEnd ausgeführt wird. Gut, Punkt. Ich werde zu aktualisieren, die Frage zu klären.
Haben Sie versucht, Fiddler?
Sie können kopieren Sie den stream in ein MemoryStream-wie Jon darauf hingewiesen, aber der Stream-Schnittstelle in einer web-Anfrage ist wirklich nur eine Abstraktion des TCP-stream nicht unterstützt, ist alle zu möglichen TCP-Operationen, die Sie durchführen können über die Steckdose (das heißt Sie könnte anfordern, dass das Paket erneut gesendet werden--aber Sie kaum jemals tun wollen, wenn Sie wollen einfach nur, um erneut die Daten zu Lesen).
Alle guten Ratschläge, danke.
InformationsquelleAutor Michael Levy | 2014-02-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
StreamReader
AnrufeDispose
auf bestimmten Datenstrom, wenn entsorgt. Verlassen Sie den stream öffnen, verwenden Sie die entsprechenden Konstruktor für dieStreamReader
.Oder noch besser, kopieren Sie es einfach in einen Puffer. Aus MSDN:
Sehen diese Frage zum Beispiel.
Und nur, um zusammenzufassen, die besten Infos aus dieser Antwort und den Hinweis oben: Wenn Sie möchten, Lesen Sie den stream zweimal, nicht mit einem StreamReader direkt gegen den zugrunde liegenden stream weil, wenn die StreamReader-geschlossen, schließt den zugrunde liegenden stream. Machen Sie einen MemoryStream kopieren, zuerst, und dann Lesen.
stream.Seek(0, SeekOrigin.Beginnen);
InformationsquelleAutor Patko
HttpContext.Current.Request.InputStream.Position=0;
Sobald Sie Lesen, geht die position auf letzten Wert, von dort ist es zu Lesen versucht, zum zweiten mal.
Also, bevor Sie weiterlesen, stellen Sie die position auf null.
Hoffe, es hilft.
HttpContext.Current
?InformationsquelleAutor ANG