Skip to content

Commit

Permalink
Allow setting parameter content type (#2249)
Browse files Browse the repository at this point in the history
* Allow setting parameter content type
* Added a test
* Add docs
  • Loading branch information
alexeyzimarev authored Jul 30, 2024
1 parent 4ddda24 commit fef25a5
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 7 deletions.
19 changes: 19 additions & 0 deletions docs/docs/usage/request.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,30 @@ request.AddParameter("name", "Væ üé", false); // don't encode the value
If you have files, RestSharp will send a `multipart/form-data` request. Your parameters will be part of this request in the form:

```
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name="parameterName"
ParameterValue
```

Sometimes, you need to override the default content type for the parameter when making a multipart form call. It's possible to do by setting the `ContentType` property of the parameter object. As an example, the code below will create a POST parameter with JSON value, and set the appropriate content type:

```csharp
var parameter = new GetOrPostParameter("someJson", "{\"attributeFormat\":\"pdf\"}") {
ContentType = "application/json"
};
request.AddParameter(parameter);
```

When the request is set to use multipart content, the parameter will be sent as part of the request with the specified content type:

```
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name="someJson"
{"attributeFormat":"pdf"}
```

You can also add `GetOrPost` parameter as a default parameter to the client. This will add the parameter to every request made by the client.

```csharp
Expand Down
37 changes: 31 additions & 6 deletions src/RestSharp/Parameters/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,29 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode
}

/// <summary>
/// MIME content type of the parameter
/// Content type of the parameter. Normally applies to the body parameter, or POST parameter in multipart requests.
/// </summary>
public ContentType ContentType { get; protected init; } = ContentType.Undefined;
public string? Name { get; }
public object? Value { get; }
public ParameterType Type { get; }
public bool Encode { get; }
public ContentType ContentType { get; set; } = ContentType.Undefined;

/// <summary>
/// Parameter name
/// </summary>
public string? Name { get; }

/// <summary>
/// Parameter value
/// </summary>
public object? Value { get; }

/// <summary>
/// Parameter type
/// </summary>
public ParameterType Type { get; }

/// <summary>
/// Indicates if the parameter value should be encoded or not.
/// </summary>
public bool Encode { get; }

/// <summary>
/// Return a human-readable representation of this parameter
Expand All @@ -48,6 +64,15 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode

protected virtual string ValueString => Value?.ToString() ?? "null";

/// <summary>
/// Creates a parameter object of based on the type
/// </summary>
/// <param name="name">Parameter name</param>
/// <param name="value">Parameter value</param>
/// <param name="type">Parameter type</param>
/// <param name="encode">Indicates if the parameter value should be encoded</param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true)
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
=> type switch {
Expand Down
28 changes: 27 additions & 1 deletion test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public MultipartFormDataTests(ITestOutputHelper output) {
_server = WireMockServer.Start();

_capturer = _server.ConfigureBodyCapturer(Method.Post);

var options = new RestClientOptions($"{_server.Url!}{RequestBodyCapturer.Resource}") {
ConfigureMessageHandler = handler => new HttpTracerHandler(handler, new OutputLogger(output), HttpMessageParts.All)
};
Expand Down Expand Up @@ -180,7 +181,7 @@ public async Task MultipartFormDataAsync() {

_capturer.Body.Should().Be(expected);
}

[Fact]
public async Task MultipartFormData_Without_File_Creates_A_Valid_RequestBody() {
using var client = new RestClient(_server.Url!);
Expand All @@ -206,4 +207,29 @@ public async Task MultipartFormData_Without_File_Creates_A_Valid_RequestBody() {
var actual = capturer.Body!.Replace("\n", string.Empty).Split('\r');
actual.Should().Contain(expectedBody);
}

[Fact]
public async Task PostParameter_contentType_in_multipart_form() {
using var client = new RestClient(_server.Url!);

var request = new RestRequest(RequestBodyCapturer.Resource, Method.Post) {
AlwaysMultipartFormData = true
};
var capturer = _server.ConfigureBodyCapturer(Method.Post);

const string parameterName = "Arequest";
const string parameterValue = "{\"attributeFormat\":\"pdf\"}";

var parameter = new GetOrPostParameter(parameterName, parameterValue) {
ContentType = "application/json"
};
request.AddParameter(parameter);

await client.ExecuteAsync(request);

var actual = capturer.Body!.Replace("\n", string.Empty).Split('\r');
actual[1].Should().Be("Content-Type: application/json; charset=utf-8");
actual[2].Should().Be($"Content-Disposition: form-data; name={parameterName}");
actual[4].Should().Be(parameterValue);
}
}

0 comments on commit fef25a5

Please sign in to comment.