Search code examples
c#restsharp.net-core-3.1

Multiple AddParameter calls only add the first parameter, ignoring the rest


Relevant project info:

  • Driver method is an XUnit project in .Net Core 3.1,
  • API is an API/MVC project in .Net Core 3.1.
  • Both are in the same solution,
  • I'm running two instances of VS 2019 in order to test and debug at this particular moment.
  • The design of the tests are setup to do a full functionality test due to required diagnostics for circumstances beyond my control and other developers in the team agree to this approach given those circumstances.

I've reviewed the recommended usage documentation at https://github.com/restsharp/RestSharp/wiki/Recommended-Usage where they are adding multiple parameters and my code is functionally identical. The trouble is that only the first parameter added is the one that makes it through to the API endpoint... That is to say that only the first parameter added makes it across the wire for the Request.Form object:

//driver method:
url = "MyURLHere";
parameters.Add(new KeyValuePair<string, string>("folderName", FolderName)); //is added
parameters.Add(new KeyValuePair<string, string>("configurationName", ConfigurationName)); //is not added
response = CallBox(url, Method.POST, parameters.ToArray(), true);

//...some time later...

private IRestResponse CallBox(string url, Method method, KeyValuePair<string, string>[] parameters = null, bool isUpload = false) {
    parameters = parameters ?? new KeyValuePair<string, string>[] { }; 

    RestClient client = new RestClient(url);
    RestRequest request = new RestRequest(method);
    foreach (KeyValuePair<string, string> param in parameters) {
        request.AddParameter(param.Key, param.Value, ParameterType.RequestBody);
    }
    request.AddHeader("content-type", "multipart/form-data; boundary=-----------------------------28947758029299");
    IRestResponse response = client.Execute(request);
    return response;
}

Important API code info:

public class BoxController : ControllerBase {
...
[HttpPost("MyURL")]
[ProducesResponseType(typeof(ActionResult), 201)]
[ProducesResponseType(typeof(ActionResult), 400)]
[ProducesResponseType(typeof(ActionResult), 500)]
public async Task<IActionResult> MyAPIEndPoint() {
...
//Checking Request.Form["ObjectKeysHere"]

What's happening here and how do I fix this issue? (Thanks)


Solution

  • What's happening here ...

    ParameterType.RequestBody can only be added once as a request only has one BODY. All subsequent additions will be ignored.

    Reference Documentation

    Request Body

    If this parameter is set, its value will be sent as the body of the request. Only one RequestBody parameter is accepted - the first one.

    note: emphasis mine.

    This confirms the issue as demonstrated in the original example provided.

    ... and how do I fix this issue?

    In this case use ParameterType.GetOrPost

    private IRestResponse CallBox(string url, Method method, KeyValuePair<string, string>[] parameters = null, bool isUpload = false) {
        parameters = parameters ?? new KeyValuePair<string, string>[] { }; 
    
        RestClient client = new RestClient(url);
        RestRequest request = new RestRequest(method);
        foreach (KeyValuePair<string, string> parameter in parameters) {
            request.AddParameter(parameter.Key, parameter.Value, ParameterType.GetOrPost);
        }        
        IRestResponse response = client.Execute(request);
        return response;
    }
    

    Reference Documentation

    Get or Post

    This behaves differently based on the method. If you execute a GET call, RestSharp will append the parameters to the Url in the form url?name1=value1&name2=value2.

    On a POST or PUT Requests, it depends on whether or not you have files attached to a Request. If not, the Parameters will be sent as the body of the request in the form name1=value1&name2=value2. Also, the request will be sent as application/x-www-form-urlencoded.

    In both cases, name and value will automatically be url-encoded.

    If you have files, RestSharp will send a multipart/form-data request. Your parameters will be part of this request in the form:

    Content-Disposition: form-data; name="parameterName"
    
    ParameterValue
    

    note: emphasis mine.