it-swarm.com.de

POST Zeichenfolge für ASP.NET Web Api-Anwendung - gibt null zurück

Ich versuche, eine Zeichenfolge vom Client an ASP.NET MVC4-Anwendung zu übertragen.

Aber ich kann den String nicht empfangen, entweder ist er null oder die post-Methode kann nicht gefunden werden (404-Fehler)

Client-Code zum Übertragen der Zeichenfolge (Konsolenanwendung):

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:49032/api/test");
request.Credentials = new NetworkCredential("user", "pw");
request.Method = "POST";
string postData = "Short test...";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;

Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

WebResponse response = request.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
dataStream = response.GetResponseStream();

StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
reader.Close();
dataStream.Close();
response.Close();
Console.ReadLine();

ASP.NET Web Api Controller:

public class TestController : ApiController
{
    [Authorize]
    public String Post(byte[] value)
    {
        return value.Length.ToString();
    }
}

In diesem Fall kann ich die Methode "Post" aufrufen, aber "value" ist NULL. Wenn ich die Methodensignatur auf (String-Wert) ändere, wird sie niemals aufgerufen.

Auch "ohne" die Einstellung [Autorisieren] hat es das seltsame Verhalten. -> Es hat also nichts mit der Benutzerauthentifizierung zu tun.

Irgendwelche Ideen, was ich falsch mache? Ich bin für jede Hilfe dankbar.

40
user1011394

Sie haben anscheinend ein Attribut [Authorize] Für Ihre Web-API-Controller-Aktion verwendet, und ich sehe nicht, wie dies für Ihre Frage relevant ist.

Also, lasst uns anfangen zu üben. So könnte ein einfacher Web-API-Controller aussehen:

public class TestController : ApiController
{
    public string Post([FromBody] string value)
    {
        return value;
    }
}

und ein Verbraucher für diese Angelegenheit:

class Program
{
    static void Main()
    {
        using (var client = new WebClient())
        {
            client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
            var data = "=Short test...";
            var result = client.UploadString("http://localhost:52996/api/test", "POST", data);
            Console.WriteLine(result);
        }
    }
}

Sie werden zweifellos die [FromBody] Dekoration des Web-API-Controller-Attributs sowie das = Präfix des POST data om Ich würde Ihnen empfehlen, mehr über zu lesen, wie die Web-API die Parameterbindung ausführt , um die Konzepte besser zu verstehen.

Das Attribut [Authorize] Kann verwendet werden, um bestimmte Aktionen auf Ihrem Server davor zu schützen, dass nur authentifizierte Benutzer darauf zugreifen können. Eigentlich ist ziemlich unklar, was Sie hier erreichen wollen. Das hätten Sie übrigens in Ihrer Frage deutlicher machen sollen. Versuchen Sie zu verstehen, wie die Parameterbindung in der ASP.NET-Web-API funktioniert (lesen Sie den Artikel, auf den ich verlinkt habe, wenn dies Ihr Ziel ist), oder versuchen Sie, eine Authentifizierung und/oder Autorisierung durchzuführen? Wenn das Zweite Ihr Fall ist, finden Sie vielleicht das following post , das ich zu diesem Thema geschrieben habe, interessant, um Ihnen den Einstieg zu erleichtern.

Und wenn Sie nach dem Lesen der Materialien, auf die ich verlinkt habe, wie ich sind und sich selbst sagen, WTF-Mann, ist alles, was ich tun muss, POST ein String an einen serverseitigen Endpunkt und ich brauche Auf keinen Fall. Dann checkout ServiceStack . Sie haben eine gute Basis für den Vergleich mit der Web-API. Ich weiß nicht, woran die Jungs von Microsoft beim Entwerfen der Web-API gedacht haben Aber im Ernst, wir sollten getrennte Basis-Controller für unsere HTML- (denken Sie an Razor) und REST Zeug? Das kann nicht ernst gemeint sein.

57
Darin Dimitrov

Die Web-API funktioniert sehr gut, wenn Sie die Tatsache akzeptieren, dass Sie HTTP verwenden. Wenn Sie versuchen, so zu tun, als würden Sie Objekte über das Kabel senden, wird es unordentlich.

 public class TextController : ApiController
    {
        public HttpResponseMessage Post(HttpRequestMessage request) {

            var someText = request.Content.ReadAsStringAsync().Result;
            return new HttpResponseMessage() {Content = new StringContent(someText)};

        }

    }

Dieser Controller verarbeitet eine HTTP-Anforderung, liest eine Zeichenfolge aus der Nutzlast und gibt diese Zeichenfolge zurück.

Sie können HttpClient zum Aufrufen verwenden, indem Sie eine Instanz von StringContent übergeben. StringContent verwendet standardmäßig text/plain als Medientyp. Welches ist genau das, was Sie versuchen zu übergeben.

    [Fact]
    public void PostAString()
    {

        var client = new HttpClient();

        var content = new StringContent("Some text");
        var response = client.PostAsync("http://Oak:9999/api/text", content).Result;

        Assert.Equal("Some text",response.Content.ReadAsStringAsync().Result);

    }
35
Darrel Miller

Darrel ist natürlich mit seiner Antwort richtig. Eine Sache, die hinzugefügt werden muss, ist der Grund, warum versucht wurde, sich an einen Körper zu binden, der ein einzelnes Token wie "Hallo" enthält.

ist, dass es sich nicht um URL-codierte Daten handelt. Indem Sie "=" wie folgt voranstellen:

=hello

es wird zu einer URL-Form-Codierung eines einzelnen Schlüsselwertpaars mit dem leeren Namen und Wert "Hallo".

Eine bessere Lösung ist jedoch, application/json beim Hochladen eines Strings zu verwenden:

POST /api/sample HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: Host:8080
Content-Length: 7

"Hello"

Mit HttpClient können Sie dies wie folgt tun:

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsJsonAsync(_baseAddress + "api/json", "Hello");
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);

Henrik

Ich benutze diesen Code, um HttpRequests zu posten.

/// <summary>
        /// Post this message.
        /// </summary>
        /// <param name="url">URL of the document.</param>
        /// <param name="bytes">The bytes.</param>
        public T Post<T>(string url, byte[] bytes)
    {
        T item;
        var request = WritePost(url, bytes);

        using (var response = request.GetResponse() as HttpWebResponse)
        {
            item = DeserializeResponse<T>(response);
            response.Close();
        }

        return item;
    }

    /// <summary>
    /// Writes the post.
    /// </summary>
    /// <param name="url">The URL.</param>
    /// <param name="bytes">The bytes.</param>
    /// <returns></returns>
    private static HttpWebRequest WritePost(string url, byte[] bytes)
    {
        ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

        HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
        Stream stream = null;
        try
        {
            request.Headers.Clear();
            request.PreAuthenticate = true;
            request.Connection = null;
            request.Expect = null;
            request.KeepAlive = false;
            request.ContentLength = bytes.Length;
            request.Timeout = -1;
            request.Method = "POST";
            stream = request.GetRequestStream();
            stream.Write(bytes, 0, bytes.Length);
        }
        catch (Exception e)
        {
            GetErrorResponse(url, e);
        }
        finally
        {
            if (stream != null)
            {
                stream.Flush();
                stream.Close();
            }
        }
        return request;
    }

Versuchen Sie es in Bezug auf Ihren Code ohne den content.Type (request.ContentType = "application/x-www-form-urlencoded";)

pdate

Ich glaube, das Problem liegt darin, wie Sie versuchen, den Wert abzurufen. Wenn Sie POST und Bytes über den Stream senden, werden diese nicht als Parameter an die Aktion übergeben. Sie müssen die Bytes über den Stream auf dem Server abrufen.

Versuchen Sie auf dem Server, die Bytes aus dem Stream abzurufen. Den folgenden Code verwende ich.

     /// <summary> Gets the body. </summary>
     /// <returns> The body. </returns>
     protected byte[] GetBytes()
     {
       byte[] bytes;
        using (var binaryReader = new BinaryReader(Request.InputStream))
        {
            bytes = binaryReader.ReadBytes(Request.ContentLength);
        }

         return bytes;
     }
3
Chuck Conway

Für WebAPI ist hier der Code zum Abrufen von Nachrichtentext ohne die spezielle Bindung [FromBody].

public class YourController : ApiController
{
    [HttpPost]
    public HttpResponseMessage Post()
    {
        string bodyText = this.Request.Content.ReadAsStringAsync().Result;
        //more code here...
    }
}
2
Jeson Martajaya

ich treffe dieses Problem und finde diesen Artikel. http://www.jasonwatmore.com/post/2014/04/18/Post-a-simple-string-value-from-AngularJS-to-NET-Web-API.aspx

Die Lösung, die ich gefunden habe, bestand darin, den Zeichenfolgenwert einfach in doppelte Anführungszeichen in Ihrem js-Post zu setzen

klappt wunderbar! Zu Ihrer Information

2
Bill.Zhuang