Skip to content

Commit 39e6e7d

Browse files
Make possible to use legacy AddParameter for Body (#1869)
* Replacement for #1817 * Added the test from #1817 * Allow also adding properly named body parameters
1 parent d3e1334 commit 39e6e7d

File tree

7 files changed

+86
-62
lines changed

7 files changed

+86
-62
lines changed

src/RestSharp/Parameters/Parameter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ public abstract record Parameter(string? Name, object? Value, ParameterType Type
3030
public override string ToString() => $"{Name}={Value}";
3131

3232
public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true)
33+
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
3334
=> type switch {
3435
ParameterType.GetOrPost => new GetOrPostParameter(name!, value?.ToString(), encode),
3536
ParameterType.UrlSegment => new UrlSegmentParameter(name!, value?.ToString()!, encode),
3637
ParameterType.HttpHeader => new HeaderParameter(name, value?.ToString()),
37-
ParameterType.RequestBody => new BodyParameter(name, value!, Serializers.ContentType.Plain),
3838
ParameterType.QueryString => new QueryParameter(name!, value?.ToString(), encode),
3939
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
4040
};

src/RestSharp/Request/RestRequest.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,10 @@ public Func<HttpResponseMessage, RestResponse>? AdvancedResponseWriter {
193193
/// Removes a parameter object from the request parameters
194194
/// </summary>
195195
/// <param name="parameter">Parameter to remove</param>
196-
public void RemoveParameter(Parameter parameter) => Parameters.RemoveParameter(parameter);
196+
public RestRequest RemoveParameter(Parameter parameter) {
197+
Parameters.RemoveParameter(parameter);
198+
return this;
199+
}
197200

198201
internal RestRequest AddFile(FileParameter file) => this.With(x => x._files.Add(file));
199202
}

src/RestSharp/Request/RestRequestExtensions.cs

+33-22
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,14 @@ public static RestRequest AddOrUpdateHeaders(this RestRequest request, ICollecti
204204
/// <param name="encode">Encode the value or not, default true</param>
205205
/// <returns></returns>
206206
public static RestRequest AddParameter(this RestRequest request, string? name, object value, ParameterType type, bool encode = true)
207-
=> request.AddParameter(Parameter.CreateParameter(name, value, type, encode));
207+
=> type == ParameterType.RequestBody
208+
? request.AddBodyParameter(name, value)
209+
: request.AddParameter(Parameter.CreateParameter(name, value, type, encode));
210+
211+
static RestRequest AddBodyParameter(this RestRequest request, string? name, object value)
212+
=> name != null && name.Contains("/")
213+
? request.AddBody(value, name)
214+
: request.AddParameter(new BodyParameter(name, value, ContentType.Plain));
208215

209216
/// <summary>
210217
/// Adds or updates request parameter of a given type. It will create a typed parameter instance based on the type argument.
@@ -218,8 +225,13 @@ public static RestRequest AddParameter(this RestRequest request, string? name, o
218225
/// <param name="type">Enum value specifying what kind of parameter is being added</param>
219226
/// <param name="encode">Encode the value or not, default true</param>
220227
/// <returns></returns>
221-
public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, object value, ParameterType type, bool encode = true)
222-
=> request.AddOrUpdateParameter(Parameter.CreateParameter(name, value, type, encode));
228+
public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, object value, ParameterType type, bool encode = true) {
229+
request.RemoveParameter(name, type);
230+
231+
return type == ParameterType.RequestBody
232+
? request.AddBodyParameter(name, value)
233+
: request.AddOrUpdateParameter(Parameter.CreateParameter(name, value, type, encode));
234+
}
223235

224236
/// <summary>
225237
/// Adds or updates request parameter, given the parameter instance, for example <see cref="QueryParameter"/> or <see cref="UrlSegmentParameter"/>.
@@ -228,13 +240,12 @@ public static RestRequest AddOrUpdateParameter(this RestRequest request, string
228240
/// <param name="request">Request instance</param>
229241
/// <param name="parameter">Parameter instance</param>
230242
/// <returns></returns>
231-
public static RestRequest AddOrUpdateParameter(this RestRequest request, Parameter parameter) {
232-
var p = request.Parameters.FirstOrDefault(x => x.Name == parameter.Name && x.Type == parameter.Type);
233-
234-
if (p != null) request.RemoveParameter(p);
243+
public static RestRequest AddOrUpdateParameter(this RestRequest request, Parameter parameter)
244+
=> request.RemoveParameter(parameter.Name, parameter.Type).AddParameter(parameter);
235245

236-
request.AddParameter(parameter);
237-
return request;
246+
static RestRequest RemoveParameter(this RestRequest request, string? name, ParameterType type) {
247+
var p = request.Parameters.FirstOrDefault(x => x.Name == name && x.Type == type);
248+
return p != null ? request.RemoveParameter(p) : request;
238249
}
239250

240251
/// <summary>
@@ -245,8 +256,7 @@ public static RestRequest AddOrUpdateParameter(this RestRequest request, Paramet
245256
/// <param name="parameters">Collection of parameter instances</param>
246257
/// <returns></returns>
247258
public static RestRequest AddOrUpdateParameters(this RestRequest request, IEnumerable<Parameter> parameters) {
248-
foreach (var parameter in parameters)
249-
request.AddOrUpdateParameter(parameter);
259+
foreach (var parameter in parameters) request.AddOrUpdateParameter(parameter);
250260

251261
return request;
252262
}
@@ -304,15 +314,15 @@ public static RestRequest AddFile(
304314
public static RestRequest AddBody(this RestRequest request, object obj, string? contentType = null) {
305315
if (contentType == null) {
306316
return request.RequestFormat switch {
307-
DataFormat.Json => request.AddJsonBody(obj, contentType ?? ContentType.Json),
308-
DataFormat.Xml => request.AddXmlBody(obj, contentType ?? ContentType.Xml),
309-
DataFormat.Binary => request.AddParameter(new BodyParameter("", obj, contentType ?? ContentType.Binary)),
310-
_ => request.AddParameter(new BodyParameter("", obj.ToString()!, contentType ?? ContentType.Plain))
317+
DataFormat.Json => request.AddJsonBody(obj),
318+
DataFormat.Xml => request.AddXmlBody(obj),
319+
DataFormat.Binary => request.AddParameter(new BodyParameter("", obj, ContentType.Binary)),
320+
_ => request.AddParameter(new BodyParameter("", obj.ToString()!, ContentType.Plain))
311321
};
312322
}
313323

314324
return
315-
obj is string str ? request.AddParameter(new BodyParameter("", str, contentType)) :
325+
obj is string str ? request.AddStringBody(str, contentType) :
316326
obj is byte[] bytes ? request.AddParameter(new BodyParameter("", bytes, contentType, DataFormat.Binary)) :
317327
contentType.Contains("xml") ? request.AddXmlBody(obj, contentType) :
318328
contentType.Contains("json") ? request.AddJsonBody(obj, contentType) :
@@ -352,7 +362,7 @@ public static RestRequest AddStringBody(this RestRequest request, string body, s
352362
/// <returns></returns>
353363
public static RestRequest AddJsonBody<T>(this RestRequest request, T obj, string contentType = ContentType.Json) where T : class {
354364
request.RequestFormat = DataFormat.Json;
355-
return request.AddParameter(new JsonParameter("", obj, contentType));
365+
return obj is string str ? request.AddStringBody(str, DataFormat.Json) : request.AddParameter(new JsonParameter("", obj, contentType));
356366
}
357367

358368
/// <summary>
@@ -366,8 +376,10 @@ public static RestRequest AddJsonBody<T>(this RestRequest request, T obj, string
366376
public static RestRequest AddXmlBody<T>(this RestRequest request, T obj, string contentType = ContentType.Xml, string xmlNamespace = "")
367377
where T : class {
368378
request.RequestFormat = DataFormat.Xml;
369-
request.AddParameter(new XmlParameter("", obj, xmlNamespace, contentType));
370-
return request;
379+
380+
return obj is string str
381+
? request.AddStringBody(str, DataFormat.Xml)
382+
: request.AddParameter(new XmlParameter("", obj, xmlNamespace, contentType));
371383
}
372384

373385
/// <summary>
@@ -401,7 +413,6 @@ static void CheckAndThrowsDuplicateKeys(ICollection<KeyValuePair<string, string>
401413
.Select(group => group.Key)
402414
.ToList();
403415

404-
if (duplicateKeys.Any())
405-
throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}");
416+
if (duplicateKeys.Any()) throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}");
406417
}
407-
}
418+
}

src/RestSharp/RestClient.Async.cs

+17-8
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public async Task<RestResponse> ExecuteAsync(RestRequest request, CancellationTo
4242
response.Request = request;
4343
response.Request.IncreaseNumAttempts();
4444

45-
return Options.ThrowOnAnyError ? ThrowIfError(response) : response;
45+
return Options.ThrowOnAnyError ? response.ThrowIfError() : response;
4646
}
4747

4848
async Task<InternalResponse> ExecuteInternal(RestRequest request, CancellationToken cancellationToken) {
@@ -130,13 +130,6 @@ static RestResponse AddError(RestResponse response, Exception exception, Cancell
130130
bool TimedOut() => timeoutToken.IsCancellationRequested || exception.Message.Contains("HttpClient.Timeout");
131131
}
132132

133-
internal static RestResponse ThrowIfError(RestResponse response) {
134-
var exception = response.GetException();
135-
if (exception != null) throw exception;
136-
137-
return response;
138-
}
139-
140133
static HttpMethod AsHttpMethod(Method method)
141134
=> method switch {
142135
Method.Get => HttpMethod.Get,
@@ -155,4 +148,20 @@ static HttpMethod AsHttpMethod(Method method)
155148
Method.Search => new HttpMethod("SEARCH"),
156149
_ => throw new ArgumentOutOfRangeException()
157150
};
151+
}
152+
153+
public static class ResponseThrowExtension {
154+
public static RestResponse ThrowIfError(this RestResponse response) {
155+
var exception = response.GetException();
156+
if (exception != null) throw exception;
157+
158+
return response;
159+
}
160+
161+
public static RestResponse<T> ThrowIfError<T>(this RestResponse<T> response) {
162+
var exception = response.GetException();
163+
if (exception != null) throw exception;
164+
165+
return response;
166+
}
158167
}

src/RestSharp/RestClientExtensions.Params.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ public static RestClient AddDefaultParameter(this RestClient client, string name
4040
/// <param name="value">Value of the parameter</param>
4141
/// <param name="type">The type of parameter to add</param>
4242
/// <returns>This request</returns>
43-
public static RestClient AddDefaultParameter(this RestClient client, string name, object value, ParameterType type)
44-
=> client.AddDefaultParameter(Parameter.CreateParameter(name, value, type));
43+
public static RestClient AddDefaultParameter(this RestClient client, string name, object value, ParameterType type) {
44+
if (type == ParameterType.RequestBody) throw new ArgumentException("Default parameter cannot be Body", nameof(type));
45+
return client.AddDefaultParameter(Parameter.CreateParameter(name, value, type));
46+
}
4547

4648
/// <summary>
4749
/// Adds a default header to the RestClient. Used on every request made by this client instance.

src/RestSharp/RestClientExtensions.cs

+14-28
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,12 @@ public static Task<RestResponse<T>> ExecuteAsync<T>(
160160
/// <returns></returns>
161161
public static async Task<T?> GetAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
162162
var response = await client.ExecuteGetAsync<T>(request, cancellationToken).ConfigureAwait(false);
163-
RestClient.ThrowIfError(response);
164-
return response.Data;
163+
return response.ThrowIfError().Data;
165164
}
166165

167166
public static async Task<RestResponse> GetAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
168167
var response = await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false);
169-
RestClient.ThrowIfError(response);
170-
return response;
168+
return response.ThrowIfError();
171169
}
172170

173171
/// <summary>
@@ -181,17 +179,15 @@ public static async Task<RestResponse> GetAsync(this RestClient client, RestRequ
181179
/// <returns></returns>
182180
public static async Task<T?> PostAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
183181
var response = await client.ExecutePostAsync<T>(request, cancellationToken).ConfigureAwait(false);
184-
RestClient.ThrowIfError(response);
185-
return response.Data;
182+
return response.ThrowIfError().Data;
186183
}
187184

188185
public static RestResponse Post(this RestClient client, RestRequest request)
189186
=> AsyncHelpers.RunSync(() => client.PostAsync(request));
190187

191188
public static async Task<RestResponse> PostAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
192189
var response = await client.ExecutePostAsync(request, cancellationToken).ConfigureAwait(false);
193-
RestClient.ThrowIfError(response);
194-
return response;
190+
return response.ThrowIfError();
195191
}
196192

197193
/// <summary>
@@ -205,14 +201,12 @@ public static async Task<RestResponse> PostAsync(this RestClient client, RestReq
205201
/// <returns></returns>
206202
public static async Task<T?> PutAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
207203
var response = await client.ExecuteAsync<T>(request, Method.Put, cancellationToken).ConfigureAwait(false);
208-
RestClient.ThrowIfError(response);
209-
return response.Data;
204+
return response.ThrowIfError().Data;
210205
}
211206

212207
public static async Task<RestResponse> PutAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
213208
var response = await client.ExecuteAsync(request, Method.Put, cancellationToken).ConfigureAwait(false);
214-
RestClient.ThrowIfError(response);
215-
return response;
209+
return response.ThrowIfError();
216210
}
217211

218212
/// <summary>
@@ -226,14 +220,12 @@ public static async Task<RestResponse> PutAsync(this RestClient client, RestRequ
226220
/// <returns></returns>
227221
public static async Task<T?> HeadAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
228222
var response = await client.ExecuteAsync<T>(request, Method.Head, cancellationToken).ConfigureAwait(false);
229-
RestClient.ThrowIfError(response);
230-
return response.Data;
223+
return response.ThrowIfError().Data;
231224
}
232225

233226
public static async Task<RestResponse> HeadAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
234227
var response = await client.ExecuteAsync(request, Method.Head, cancellationToken).ConfigureAwait(false);
235-
RestClient.ThrowIfError(response);
236-
return response;
228+
return response.ThrowIfError();
237229
}
238230

239231
/// <summary>
@@ -247,14 +239,12 @@ public static async Task<RestResponse> HeadAsync(this RestClient client, RestReq
247239
/// <returns></returns>
248240
public static async Task<T?> OptionsAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
249241
var response = await client.ExecuteAsync<T>(request, Method.Options, cancellationToken).ConfigureAwait(false);
250-
RestClient.ThrowIfError(response);
251-
return response.Data;
242+
return response.ThrowIfError().Data;
252243
}
253244

254245
public static async Task<RestResponse> OptionsAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
255246
var response = await client.ExecuteAsync(request, Method.Options, cancellationToken).ConfigureAwait(false);
256-
RestClient.ThrowIfError(response);
257-
return response;
247+
return response.ThrowIfError();
258248
}
259249

260250
/// <summary>
@@ -268,14 +258,12 @@ public static async Task<RestResponse> OptionsAsync(this RestClient client, Rest
268258
/// <returns></returns>
269259
public static async Task<T?> PatchAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
270260
var response = await client.ExecuteAsync<T>(request, Method.Patch, cancellationToken).ConfigureAwait(false);
271-
RestClient.ThrowIfError(response);
272-
return response.Data;
261+
return response.ThrowIfError().Data;
273262
}
274263

275264
public static async Task<RestResponse> PatchAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
276265
var response = await client.ExecuteAsync(request, Method.Patch, cancellationToken).ConfigureAwait(false);
277-
RestClient.ThrowIfError(response);
278-
return response;
266+
return response.ThrowIfError();
279267
}
280268

281269
/// <summary>
@@ -289,14 +277,12 @@ public static async Task<RestResponse> PatchAsync(this RestClient client, RestRe
289277
/// <returns></returns>
290278
public static async Task<T?> DeleteAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
291279
var response = await client.ExecuteAsync<T>(request, Method.Delete, cancellationToken).ConfigureAwait(false);
292-
RestClient.ThrowIfError(response);
293-
return response.Data;
280+
return response.ThrowIfError().Data;
294281
}
295282

296283
public static async Task<RestResponse> DeleteAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
297284
var response = await client.ExecuteAsync(request, Method.Delete, cancellationToken).ConfigureAwait(false);
298-
RestClient.ThrowIfError(response);
299-
return response;
285+
return response.ThrowIfError();
300286
}
301287

302288
/// <summary>

test/RestSharp.Tests/RestContentTests.cs

+13
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,17 @@ public void RestContent_CaseInsensitiveHeaders() {
1212

1313
httpContent.Headers.ContentType!.MediaType.Should().Be(myContentType);
1414
}
15+
16+
[Fact]
17+
public void RestContent_supports_manual_json_body() {
18+
const string myContentType = "application/json";
19+
const string myJsonString = "[]";
20+
21+
var request = new RestRequest("resource").AddParameter(myContentType, myJsonString, ParameterType.RequestBody);
22+
var content = new RequestContent(new RestClient(), request);
23+
24+
var httpContent = content.BuildContent();
25+
26+
httpContent.Headers.ContentType!.MediaType.Should().Be(myContentType);
27+
}
1528
}

0 commit comments

Comments
 (0)