简体   繁体   中英

MVC API sending data in the body

I am trying to send data to a API it works fine using Postman but I am not sure how to do it in code.

I created this method that is using test json string and it send the data in the body. When I debug it the error is coming from this line

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

and I get the message

The remote server returned an error: (400) Bad Request.' "

Any help will be great not sure what I am doing wrong.

public static T Post<T>(string httpMethod, string url, object model)
        {
            var fullUrl = apiUrl + url;

            var json = "{\"FirstName\":\"1\",\"LastName\":\"1\"}";


            string data = json;

            Stream dataStream = null;
            WebRequest Webrequest;
            Webrequest = WebRequest.Create(fullUrl);


            Webrequest.ContentType = "application/json";
            Webrequest.Method = WebRequestMethods.Http.Post;

            Webrequest.PreAuthenticate = true;
            Webrequest.Headers.Add("Authorization", "Bearer Toeke n");

            byte[] byteArray = Encoding.UTF8.GetBytes(data);

            Webrequest.ContentLength = byteArray.Length;

            dataStream = Webrequest.GetRequestStream();

            using (dataStream = Webrequest.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);
            }

            WebResponse response = Webrequest.GetResponse();
    }

API

 [HttpPost]
        public IHttpActionResult SaveForm(RequestWeb Request)

Postman Raw

{
    "FirstName": "1",
    "LastName": "1",
}

If possible, consider using HttpClient instead

Simplified example

//...Assuming an static HttpClient
static HttpClient client;
    
public static async Task<T> PostAsync<T>(string url, object model) {
    var fullUrl = apiUrl + url;

    //Assuming object model will be converted to JSON
    string json = "{\"FirstName\":\"1\",\"LastName\":\"1\"}";

    string data = json;
    
    httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Bearer", "Token");
            
    var content = new StringContent(data, Encoding.UTF8, "application/json");

    HttpResponseMessage response = await httpClient.PostAsync(new Uri(fullUrl), content);
    
    T resp = await response.Content.ReadAsAsync<T>();
    
    return resp;
}

I would also suggest explicitly telling the Server to expect the data in the request body

[HttpPost]
public IHttpActionResult SaveForm([FromBody]RequestWeb Request)

Is there any specific reason for you using WebRequest instead of HttpClient ? If you're not doing any FTP work and you're using .NET Framework 4.5+ or .NET Core you're better off migrating to HttpClient as it gives you easier usage flow, comes with async support out of the box and is quite easier to mock and test, while giving you more functionality on top of that. Overall, it is the modern API for making requests from .NET.

public async Task<T> Post<T>(object model) // use actual model type instead of type object
{
    var url = "Specify URL";
    var token = "Specify Token";

    var payload = JsonSerializer.Serialize(model);

    // Preferably get the instance from dependency injection or hoist it as a private variable in the class body.
    // In any case, don't recreate it like we're doing here.
    var client = new HttpClient();

    var requestMessage = new HttpRequestMessage(HttpMethod.Post, url);

    requestMessage.Headers.Add("Authorization", $"Bearer {token}");
    requestMessage.Content = new StringContent(payload, Encoding.UTF8, "application/json");

    var responseMessage = await client.SendAsync(requestMessage);

    if (responseMessage.IsSuccessStatusCode)
    {
        var result = await responseMessage.Content.ReadAsStringAsync();

        return JsonSerializer.Deserialize<T>(result);
    }
    else
    {
        // Handle error result
        throw new Exception();
    }            
}

I'd recommend using Flurl. It's a "fluent" HTTP client that is short, sweet and elegant. Extensible, and testable, too.

https://flurl.dev/

It's [most] a bunch of extension methods along with a few helper classes that wrap the core.Net bits. Posting JSON to an API can be as simple as this (example from Flurl):

Person person = await "https://api.com"
                .AppendPathSegment("person")
                .SetQueryParams(new {
                  a = 1 ,
                  b = 2
                })
                .WithOAuthBearerToken("my_oauth_token")
                .PostJsonAsync(new {
                  first_name = "Claire" ,
                  last_name  = "Underwood"
                })
                .ReceiveJson<Person>();

Your use case might look something like this:

using Flurl;
using Flurl.Http;
. . .
private static async TResponseBody PostToSomeApi<TRequestBody,TResponseBody>(
  string path,
  TRequestBody requestBody
)
{
  const string  token    = "this-is-my-oauth-bearer-token";
  TResponseBody response = await
                           "https://my.special.urlcom/api/xyz"
                           .AppendPathSegment( path )
                           .WithOAuthBearerToken( token )
                           .AllowHttpStatus( "200" )
                           .PostJsonAsync( requestBody )
                           .ReceiveJsonAsync<TResponseBody>()
                           ;
  return response;
}

And you can get fancier if you need to inject logging or examine response headers, deal with cookies, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM