Laden...

WebRequest: Inhaltsteil mit diesem Verbtyp kann nicht gesendet werden.

Erstellt von Sweeny vor einem Jahr Letzter Beitrag vor einem Jahr 1.478 Views
S
Sweeny Themenstarter:in
8 Beiträge seit 2023
vor einem Jahr
WebRequest: Inhaltsteil mit diesem Verbtyp kann nicht gesendet werden.

Hallo zusammen,

ich entwickle mit dem .NET Framework 4.5 ein Baustein für ein Smart-Home-System. Genauer gesagt will ich über eine API zuerst eine Authentifizierung erreichen (klappt), dann Daten abrufen (klappt) und weitere Daten über einen weiteren Aufruf abrufen (klappt nicht).

Zuerst brauche ich POST, erhalte nach der Authentifizierung Cookies, die ich in einem CookieContainer speichere (klappt), diesen verwende ich dann wieder bei einem POST-Aufruf (klappt), dann benötige ich nochmals die Cookies für einen GET-Aufruf (klappt nicht). Da erhalte ich dann die Fehlermeldung "Inhaltsteil mit diesem Verbtyp kann nicht gesendet werden.".

Ich habe über Google herausgefunden, dass die Cookies nicht so einfach über GET übermittelt werden können?

Ich würde mich sehr über eine Idee freuen!

Alex

NUR AUSSCHNITT:


        public const string userAgent = "Mozilla/5.0 (Windows NT 6.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1";
        public CookieContainer cookieJar;

        private CookieContainer Login(string username, string password, string loginPageURL)
        {
            // Create a request using the provied URL. 
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(loginPageURL);

            // Set the Method property of the request to POST.
            request.Method = "POST";

            // Set the Cookiecontainer
            CookieContainer cookieJar = new CookieContainer();
            request.CookieContainer = cookieJar;

            // Create POST data and convert it to a byte array.
            //string postData = "username=" + username + "&password=" + password;
            //byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";

            // Set the User Agent
            request.UserAgent = userAgent;

            // Set the ContentLength property of the WebRequest.
            //request.ContentLength = byteArray.Length;

            // Get the request stream.
            Stream dataStream = request.GetRequestStream();

            // Write the data to the request stream.
            //dataStream.Write(byteArray, 0, byteArray.Length);

            // Close the Stream object.
            dataStream.Close();

            // Get the response.
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            // Get the stream containing content returned by the server.
            dataStream = response.GetResponseStream();

            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);

            // Read the content.
            string responseFromServer = reader.ReadToEnd();

            string cookie = cookieJar.GetCookieHeader(request.RequestUri);

            Login ID = JsonConvert.DeserializeObject<Login>(responseFromServer);

            this.PlantID.Value = ID.Back.Data[0].PlantId;

            // Clean up the streams.
            reader.Close();
            dataStream.Close();
            response.Close();

            return cookieJar;
        }

        private string ViewPageGET(CookieContainer cookieJar, string pageURL)
        {
            string str = string.Empty;

            HttpWebRequest request2 = (HttpWebRequest)WebRequest.Create(pageURL);

            // Set the Method property of the request to GET.
            request2.Method = "GET";

            // Put session back into CookieContainer
            request2.CookieContainer = cookieJar;

            // Get the request stream.
            Stream dataStream2 = request2.GetRequestStream();

            // Close the Stream object.
            dataStream2.Close();

            // Get the response.
            HttpWebResponse response2 = (HttpWebResponse)request2.GetResponse();

            // Get the stream containing content returned by the server.
            dataStream2 = response2.GetResponseStream();

            // Open the stream using a StreamReader for easy access.
            StreamReader reader2 = new StreamReader(dataStream2);

            // Read the content.
            str = reader2.ReadToEnd();

            return str;
        }

        public override void Execute()
        {
            if (this.Trigger.WasSet && this.Trigger.HasValue)
            {

                 try
                {
                    // URL für Login
                    string loginPageURL = "https://server.growatt.com/newTwoLoginAPI.do?userName=" + this.Benutzername + "&password=" + MD5Passwort;

                    // URL für Jahresproduktion - GET
                    string pageURL2 = "https://server.growatt.com/newPlantDetailAPI.do?plantId=" + this.PlantID + "&date=" + DateTime.Now.Year.ToString() + "&type=3";

                    // URL für Tagesproduktion - GET
                    string pageURL3 = "https://server.growatt.com/newPlantDetailAPI.do?plantId=" + this.PlantID + "&date=" + DateTime.Now.Date.ToString("yyyy-mm-dd") + "&type=1";

                    // Login-Aufruf
                    cookieJar = Login(this.Benutzername, this.Passwort, loginPageURL);

                    // Aufruf 2. API (GET)
                    Root2 Growattlogin2 = JsonConvert.DeserializeObject<Root2>(ViewPageGET(cookieJar, pageURL2));

                    // Aufruf 3. API (GET)
                   Root2 Growattlogin3 = JsonConvert.DeserializeObject<Root2>(ViewPageGET(cookieJar, pageURL3));

                    this.Year.Value = (float) Convert.ToDouble(Growattlogin2.Back.PlantData.CurrentEnergy.Replace(" kWh", ""));
                    this.Today.Value = (float) Convert.ToDouble(Growattlogin3.Back.PlantData.CurrentEnergy.Replace(" kWh", ""));

                    this.Fehler.Value = string.Empty;
                }
                catch (Exception ex)
                {
                    this.Fehler.Value = ex.Message;
                }
            }
}

16.806 Beiträge seit 2008
vor einem Jahr

Ich habe über Google herausgefunden, dass die Cookies nicht so einfach über GET übermittelt werden können?

Keine Ahnung, wo Du das gefunden hast und in welchem Zusammenhang das steht (daher gibt man i.d.R. bei so einer Aussage die Quelle an) - aber natürlich kannst Du bei GET-Anfragen Cookies mitgeben. Sonst würde das Internet nicht funktionieren.

Und wenn ich> Fehlermeldung:

Inhaltsteil mit diesem Verbtyp kann nicht gesendet werden.

lese, dann wird sofort klar: Du wirst Dich leichter tun, wenn Du Dein Dev-System/SDK auf Englisch stellst, die originalen Fehlermeldungen bekommst (die dann Englisch sind) und danach googelst. Mit so einer Fehlermeldung wirst Du vermutlich kaum hilfreiche Fehlerlösungen im Netz finden - fast niemand (in Summe) entwickelt mit lokalisierten Sprachen.

Die Fehlermeldung kommt eigentlich, wenn Du einen GET Request mit Body hast. Denn wenn man Body scheisse übersetzt, wird "Inhaltsteil" draus, woraus dann klar wird, woran es liegen wird. Hättest Du die originale Fehlermeldung vor Dir ("Cannot send a content-body with this verb-type") wäre Dir das Problem eventuell auch sofort aufgefallen.
Tu Dir also selbst nen Gefallen, schon Deine Nerven und entwickle nicht mit einem deutschen SDK mit schlechten Übersetzungen - egal welche Programmiersprache / Runtime Du nutzt.

Laut HTTP Standard funktioniert das in der Theorie (zumindest ist es Teil des RFCs), aber der WebRequest kann das nicht - machst Du aber.
Leider sagst Du nicht, wo die Exception geworfen wird, aber ich bin mir sehr sicher, dass es bei GetRequestStream ist - weil das den Body ausführt.

Wenn Du den WebRequest beibehalten willst (was ich Dir nicht empfehle, genauso wenig die .NET Docs) - dann musst Du direkt bei Get auf den Response gehen.


WebRequest request = WebRequest.Create(uri);
request.Method = "GET";
request.CookieContainer ....
using (WebResponse response = request.GetResponse())
using (Stream stream = response.GetResponseStream())
{
      ...
}

Aber das brauchst Du eigentlich alles nicht, wenn Du einfach HttpClient oder Refit verwenden würdest, die Dir beide den ganzen Overhead abnehmen.
Seit Jahren (>10) gibt es die Empfehlung WebRequest nicht mehr direkt zu verwenden.
Sparst Dir 99% von dem Code, den Du hier gepostet hast.

S
Sweeny Themenstarter:in
8 Beiträge seit 2023
vor einem Jahr

Wenn Du den WebRequest beibehalten willst (was ich Dir nicht empfehle, genauso wenig die .NET Docs) - dann musst Du direkt bei Get auf den Response gehen.

Danke, Dir, Abt.
Ich werde mir HTTPClient genauer ansehen; hier aber noch der Abschluss mit WebRequest.

So sieht jetzt der Part aus:


        private string ViewPageGET(CookieContainer cookieJar, string pageURL)
        {
            string str = string.Empty;

            WebRequest request = WebRequest.Create(pageURL);
            request.Method = "GET";
            request.CookieContainer = cookieJar;
            using (WebResponse response = request.GetResponse())
            using (Stream stream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                String responseString = reader.ReadToEnd();
                return responseString;
            }
        }

Allerdings wird mir für die Zeile 7 mit dem CookieContainer angezeigt: > Fehlermeldung:

Fehler CS1061 "WebRequest" enthält keine Definition für "CookieContainer", und es wurde keine verfügbare CookieContainer-Erweiterungsmethode gefunden, die ein erstes Argument vom Typ "WebRequest" akzeptiert (möglicherweise fehlt eine using-Direktive oder ein Assemblyverweis).

Hättest Du da noch einen Tipp für mich?

Viele Grüße
Alex

4.931 Beiträge seit 2008
vor einem Jahr

WebRequest ist eine abstrakte Klasse, nur die davon abgeleitete Klasse HttpWebRequest verfügt über die Eigenschaft CookieContainer: sieh dir das Beispiel dort an, du mußt also entsprechend casten.

S
Sweeny Themenstarter:in
8 Beiträge seit 2023
vor einem Jahr

Danke Euch. Ich habe es geschafft!

Viele Grüße

Alex