From fef25a56d57f6ac8377d34ce50451ef3be95e9e7 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Tue, 30 Jul 2024 03:09:56 -0400 Subject: [PATCH] Allow setting parameter content type (#2249) * Allow setting parameter content type * Added a test * Add docs --- docs/docs/usage/request.md | 19 ++++++++++ src/RestSharp/Parameters/Parameter.cs | 37 ++++++++++++++++--- .../MultipartFormDataTests.cs | 28 +++++++++++++- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/docs/docs/usage/request.md b/docs/docs/usage/request.md index fd8eef508..374ee14dd 100644 --- a/docs/docs/usage/request.md +++ b/docs/docs/usage/request.md @@ -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 diff --git a/src/RestSharp/Parameters/Parameter.cs b/src/RestSharp/Parameters/Parameter.cs index 903b33402..b23c592dc 100644 --- a/src/RestSharp/Parameters/Parameter.cs +++ b/src/RestSharp/Parameters/Parameter.cs @@ -32,13 +32,29 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode } /// - /// MIME content type of the parameter + /// Content type of the parameter. Normally applies to the body parameter, or POST parameter in multipart requests. /// - 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; + + /// + /// Parameter name + /// + public string? Name { get; } + + /// + /// Parameter value + /// + public object? Value { get; } + + /// + /// Parameter type + /// + public ParameterType Type { get; } + + /// + /// Indicates if the parameter value should be encoded or not. + /// + public bool Encode { get; } /// /// Return a human-readable representation of this parameter @@ -48,6 +64,15 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode protected virtual string ValueString => Value?.ToString() ?? "null"; + /// + /// Creates a parameter object of based on the type + /// + /// Parameter name + /// Parameter value + /// Parameter type + /// Indicates if the parameter value should be encoded + /// + /// public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true) // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault => type switch { diff --git a/test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs b/test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs index 389329235..28d0ac825 100644 --- a/test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs +++ b/test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs @@ -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) }; @@ -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!); @@ -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); + } } \ No newline at end of file