Httpclient consume web api via console app C#

2019-09-15 07:03发布

问题:

I am trying to consume the below web api via console app using Httpclient. I am stuck as in how to pass the parameter. The paramter is coming as a command line argument. This is my Rest api

[HttpPost, Route("Test")]
        public IHttpActionResult Test(bool sample = false)
        {             
                return Ok();
        }

The parameter comes in this was as command line argument

/Parameters:sample=true.

Here is how I am parsing out the parameter in the console app

 static int Main(string[] args)
        {

                if (args.Length == 0)
                {
                    Console.Error.WriteLine("No action provided.");
                    return -1;
                }
                foreach (string param in args)
                {
                    switch (param.Substring(0, param.IndexOf(":")))
                    {
                        case "/Action":
                            action = param.Substring(param.IndexOf(":") + 1);
                            break;
                        case "/Parameters":
                            parameter = param.Substring(param.IndexOf(":") + 1);
                            break;    
                    }
                }
            return 0;
        }

Once I get my parameter which is in this format

parameter = "sample=true"

I am trying to invoke the web api call but unable to pass the parameter value. can anybody pin point what I am doing wrong

    client.BaseAddress = new Uri(ConfigurationManager.AppSettings.Get("BaseWebApiUrl"));
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    var apiUrl = GetApiURL();


                   var Context = new StringContent(JsonConvert.SerializeObject(parameter), Encoding.UTF8, "application/json");

 var respFeed = await client.PostAsync(apiUrl, Context);

回答1:

By default in Web Api basic type parameters are never bound to the body of the request.

If you want to forcefully bind your bool parameter with the request body you need to decorate it with FromBodyAttribute:

[HttpPost, Route("Test")]
public IHttpActionResult Test([FromBody] bool sample = false)
{             
    return Ok();
}

Be aware that even if you do this your request is not valid for Web Api. A single basic type parameter must be passed with a specific format. In your case your request body must be the following:

=true

A better approach is to turn your Action parameter into a class:

public class TestModel
{
    public bool Sample { get; set; }
}

[HttpPost, Route("Test")]
public IHttpActionResult Test(TestModel model)
{
    return Ok();
}

This way you will be able to send a Json object as request body, like:

{
    "sample": true
}

This is a small example of how you could achieve such a result:

var parameterDictionary = parameter.Split("=").ToDictionary(s => s[0], s => bool.Parse(s[1]));
var json = JsonConvert.SerializeObject(parameterDictionary);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var respFeed = await client.PostAsync(apiUrl, content);


回答2:

You should pass it as a part of the url.

private void CallService(bool sample)
{
    client.BaseAddress = new Uri(ConfigurationManager.AppSettings.Get("BaseWebApiUrl"));
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var apiUrl = $"http://yourserver:port/api/somecontroller/?sample={sample}";

    var Context = new StringContent(JsonConvert.SerializeObject(parameter), Encoding.UTF8, "application/json");

    var respFeed = await client.PostAsync(apiUrl, Context);
}


回答3:

First, change your method signature to

public IHttpActionResult Test([FromBody]bool sample = false)

since primitive types are resolved from URL/Query String and not body. By adding FromBody attribute will force it to resolve from the body.

Next, since you said you have parameter value as var parameter = "sample=true";, change your parameter construction to

var jsonParam = new { sample = parameter.split('=')[1]}; // I'm leaving null checks and validation for simplicity
var Context = new StringContent(JsonConvert.SerializeObject(jsonParam), Encoding.UTF8, "application/json");