0

Once I'm trying to call web API controller method I'm getting this error,

Cannot send a content-body with this verb-type.

My Details controller as follows,

[HttpGet("requestDetails/Details")]
public IActionResult GetDetails([FromHeader] int tenantId,[FromBody]ParamterDTO pdto)
{
    try
    {
        var details = Service.GetDetials(pdto.FromDate, pdto.SearchText, pdto.UserId);
        return Ok(details);
    }
    catch (Exception)
    {
        return StatusCode(500);
    }
}

This how I consume Details controller method.

public string GetDetails(string fromDate, string searchText, string userID) {

  try {
    string serviceUrl = "http://localhost/Testapi/api/details/requestDetails/Details";

    string jsonParamterData = new JavaScriptSerializer().Serialize(new {
      FromDate = fromDate,
        SearchText = searchText,
        UserId = userID
    });

    HttpClient client = new HttpClient();

    HttpMethod method = new HttpMethod("GET");
    HttpRequestMessage message = new HttpRequestMessage(method, serviceUrl);

    StringContent content = new StringContent(jsonParamterData, Encoding.UTF8, "application/json");
    client.DefaultRequestHeaders.Add("TenantId", tenantId.ToString());
    client.DefaultRequestHeaders.Add("Authorization", string.Format("bearer {0}", token));
    message.Content = content;

    var response = client.SendAsync(message).Result;
    client.Dispose();
    return response.Content.ToString();
  } catch (Exception ex) {
    NameValueCollection logParams = new NameValueCollection();
    Logger.LogErrorEvent(ex, logParams);
    throw;
  }
}

Can anyone explain me, what did I do wrong here.

Updated:

I used post instead of get by changing code as,

HttpMethod method = new HttpMethod("POST");
HttpRequestMessage message = new HttpRequestMessage(method, serviceUrl);

StringContent content = new StringContent(jsonParamterData, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("TenantId", tenantId.ToString());
client.DefaultRequestHeaders.Add("Authorization", string.Format("bearer {0}", token));
message.Content = content;
//var response = client.GetStringAsync(message.).Result;
var response = client.SendAsync(message);

but response result showing as follows,

enter image description here

thomsan
  • 433
  • 5
  • 19
  • 1
    You have to use a "post" – Caspar Kleijne Jan 12 '21 at 20:59
  • Does this answer your question? [How to use HttpClient to send content in body of GET request?](https://stackoverflow.com/questions/43421126/how-to-use-httpclient-to-send-content-in-body-of-get-request) – Brachy Jan 12 '21 at 21:04
  • @CasparKleijne Is this correct way to access response data? `var response = client.SendAsync(message).Result; client.Dispose(); return response.Content.ToString();` – thomsan Jan 12 '21 at 21:05
  • @CasparKleijne I used post and its hit the controller method. but api returned data not access. `var response` value showing as `statusCode 200 ReasonPharse 'ok'` – thomsan Jan 12 '21 at 21:10
  • What do you need int tenantId for? it is not used? – Serge Jan 12 '21 at 21:14
  • @CasparKleijne Sir can u please look on this, after change it into post controller method hi, but response showing me as https://i.stack.imgur.com/58TQ0.png – thomsan Jan 12 '21 at 21:26

2 Answers2

0

Try to change your action to this:

[Route("requestDetails/Details")]
public ActionResult<Details> GetDetails([FromBody] ParamterDTO pdto)
{
    try
    {
return Service.GetDetials(pdto.FromDate, pdto.SearchText, pdto.UserId);
    //or you can try    
return Ok(Service.GetDetials(pdto.FromDate, pdto.SearchText, pdto.UserId)); 
   // but you need special deserialization
      
    }
    catch (Exception)
    {
        return StatusCode(StatusCodes.Status500InternalServerError, new Details());
    }
}

And change your request code to this:

using (var client = new HttpClient())
{
    ....your code 
        
    
    var response = client.SendAsync(message);

    if (response.IsSuccessStatusCode)
    {
        return response.Content.ReadAsStringAsync().Result;
                
    }
   ````your code
}
Serge
  • 40,935
  • 4
  • 18
  • 45
0

Maybe try some different approach. If you can OFC...

I did some quick try with code similar to yours.

Look at this...

Controller method:

    [HttpPost]
    public IActionResult GetDetails([FromHeader] int tenantId, [FromBody] ParameterDto parameter)
    {
        try
        {
            return Ok(parameter);
        }
        catch (Exception)
        {
            return StatusCode(500);
        }
    }

Very simple just to show that's works, and there is no custom routing, but I assumed that is no issue here.

Also for the need of my sample I hosted this at localhost (standalone in console).

And here is my API consumer code:

    public static async Task<ParameterDto> Post(ParameterDto dto)
    {
        var _restClient = new RestClient("http://localhost:5000");
        var body = dto != null ? JsonConvert.SerializeObject(dto) : null;

        var request = new RestRequest("/details", Method.POST);

        var absoluteUri = _restClient.BuildUri(request).AbsoluteUri;

        request.AddHeader("TenantId", "2");
        request.AddParameter("application/json; charset=utf-8", body, ParameterType.RequestBody);
        _restClient.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

        var response = await _restClient.ExecuteTaskAsync(request);

        if (response.ResponseStatus != ResponseStatus.Completed || !IsSuccess(response.StatusCode) ||
               response.StatusCode == HttpStatusCode.BadRequest || response.StatusCode == HttpStatusCode.Unauthorized)
        {
            var message = string.Format("POST request failed. Code: {0}, Status: {1}",
                response.StatusCode, response.ResponseStatus);

            throw new Exception(message);
        }

        return JsonConvert.DeserializeObject<ParameterDto>(response.Content);
    }

    public static bool IsSuccess(HttpStatusCode httpStatusCode)
    {
        return (int)httpStatusCode >= 200 && (int)httpStatusCode <= 299;
    }

As you can see there is some boilerplate code, but I'm using this method sometimes so I just copy my code.

It works like a charm!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Patryk
  • 41
  • 3