From 30dfdf6d7551b801ace17a9d8777955c5d311f48 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Tue, 18 Jan 2022 11:33:18 +0100 Subject: [PATCH 1/5] Dispose HttpClient conditionally --- src/RestSharp/RestClient.cs | 113 +++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 46 deletions(-) diff --git a/src/RestSharp/RestClient.cs b/src/RestSharp/RestClient.cs index 56fa2476f..96f9e4d05 100644 --- a/src/RestSharp/RestClient.cs +++ b/src/RestSharp/RestClient.cs @@ -38,62 +38,28 @@ public partial class RestClient : IDisposable { internal RestClientOptions Options { get; } - /// - /// Default constructor that registers default content handlers - /// - public RestClient() : this(new RestClientOptions()) { } - - public RestClient(HttpClient httpClient, RestClientOptions? options = null) { - UseDefaultSerializers(); - - HttpClient = httpClient; - Options = options ?? new RestClientOptions(); - CookieContainer = Options.CookieContainer ?? new CookieContainer(); - - if (Options.Timeout > 0) - HttpClient.Timeout = TimeSpan.FromMilliseconds(Options.Timeout); - HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(Options.UserAgent); - } - - public RestClient(HttpMessageHandler handler) : this(new HttpClient(handler)) { } - public RestClient(RestClientOptions options) { UseDefaultSerializers(); - Options = options; - CookieContainer = Options.CookieContainer ?? new CookieContainer(); - - var handler = new HttpClientHandler { - Credentials = Options.Credentials, - UseDefaultCredentials = Options.UseDefaultCredentials, - CookieContainer = CookieContainer, - AutomaticDecompression = Options.AutomaticDecompression, - PreAuthenticate = Options.PreAuthenticate, - AllowAutoRedirect = Options.FollowRedirects, - Proxy = Options.Proxy - }; + Options = options; + CookieContainer = Options.CookieContainer ?? new CookieContainer(); + _disposeHttpClient = true; - if (Options.RemoteCertificateValidationCallback != null) - handler.ServerCertificateCustomValidationCallback = - (request, cert, chain, errors) => Options.RemoteCertificateValidationCallback(request, cert, chain, errors); - - if (Options.ClientCertificates != null) { - handler.ClientCertificates.AddRange(Options.ClientCertificates); - handler.ClientCertificateOptions = ClientCertificateOption.Manual; - } - - if (Options.MaxRedirects.HasValue) - handler.MaxAutomaticRedirections = Options.MaxRedirects.Value; + var handler = new HttpClientHandler(); + ConfigureHttpMessageHandler(handler); var finalHandler = Options.ConfigureMessageHandler?.Invoke(handler) ?? handler; HttpClient = new HttpClient(finalHandler); - if (Options.Timeout > 0) - HttpClient.Timeout = TimeSpan.FromMilliseconds(Options.Timeout); - HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(Options.UserAgent); + ConfigureHttpClient(HttpClient); } + /// + /// Creates an instance of RestClient using the default + /// + public RestClient() : this(new RestClientOptions()) { } + /// /// /// Sets the BaseUrl property for requests made by this client instance @@ -108,6 +74,57 @@ public RestClient(Uri baseUrl) : this(new RestClientOptions { BaseUrl = baseUrl /// public RestClient(string baseUrl) : this(new Uri(Ensure.NotEmptyString(baseUrl, nameof(baseUrl)))) { } + public RestClient(HttpClient httpClient, RestClientOptions? options = null, bool disposeHttpClient = false) { + if (Options?.CookieContainer != null) { + throw new ArgumentException("Custom cookie container cannot be added to the HttpClient instance", nameof(options.CookieContainer)); + } + + UseDefaultSerializers(); + + HttpClient = httpClient; + Options = options ?? new RestClientOptions(); + CookieContainer = new CookieContainer(); + _disposeHttpClient = disposeHttpClient; + + ConfigureHttpClient(HttpClient); + } + + /// + /// Creates a new instance of RestSharp using the message handler provided. By default, HttpClient disposes the provided handler + /// when the client itself is disposed. If you want to keep the handler not disposed, set disposeHandler argument to false. + /// + /// Message handler instance to use for HttpClient + /// Dispose the handler when disposing RestClient, true by default + public RestClient(HttpMessageHandler handler, bool disposeHandler = true) : this(new HttpClient(handler, disposeHandler)) { } + + void ConfigureHttpClient(HttpClient httpClient) { + if (Options.Timeout > 0) + httpClient.Timeout = TimeSpan.FromMilliseconds(Options.Timeout); + httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(Options.UserAgent); + } + + void ConfigureHttpMessageHandler(HttpClientHandler handler) { + handler.Credentials = Options.Credentials; + handler.UseDefaultCredentials = Options.UseDefaultCredentials; + handler.CookieContainer = CookieContainer; + handler.AutomaticDecompression = Options.AutomaticDecompression; + handler.PreAuthenticate = Options.PreAuthenticate; + handler.AllowAutoRedirect = Options.FollowRedirects; + handler.Proxy = Options.Proxy; + + if (Options.RemoteCertificateValidationCallback != null) + handler.ServerCertificateCustomValidationCallback = + (request, cert, chain, errors) => Options.RemoteCertificateValidationCallback(request, cert, chain, errors); + + if (Options.ClientCertificates != null) { + handler.ClientCertificates.AddRange(Options.ClientCertificates); + handler.ClientCertificateOptions = ClientCertificateOption.Manual; + } + + if (Options.MaxRedirects.HasValue) + handler.MaxAutomaticRedirections = Options.MaxRedirects.Value; + } + internal Func Encode { get; set; } = s => s.UrlEncode(); internal Func EncodeQuery { get; set; } = (s, encoding) => s.UrlEncode(encoding)!; @@ -176,5 +193,9 @@ void DoBuildUriValidations(RestRequest request) { ); } - public void Dispose() => HttpClient.Dispose(); + public void Dispose() { + if (_disposeHttpClient) HttpClient.Dispose(); + } + + readonly bool _disposeHttpClient; } \ No newline at end of file From f58d9c419210385d8bac72a926ae9be686f91861 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Wed, 19 Jan 2022 13:14:01 +0100 Subject: [PATCH 2/5] Replaced Twilio example with Twitter --- docs/usage.md | 187 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 75 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index ae92a81f5..d47fc2221 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -2,114 +2,142 @@ title: Usage --- -## Recommended Usage +## Recommended usage -RestSharp works best as the foundation for a proxy class for your API. Here are a couple of examples from the Twilio library. +RestSharp works best as the foundation for a proxy class for your API. Each API would most probably require different settings for `RestClient`, so a dedicated API class (and its interface) gives you a nice isolation between different `RestClient` instances, and make them testable. -Create a class to contain your API proxy implementation with an `ExecuteAsync` (or any of the extensions) method for funneling all requests to the API. -This allows you to set commonly-used parameters and other settings (like authentication) shared across requests. -Because an account ID and secret key are required for every request you are required to pass those two values when -creating a new instance of the proxy. +Essentially, RestSharp is a wrapper around `HttpClient` that allows you to do the following: +- Add default parameters of any kind (not just headers) to the client, once +- Add parameters of any kind to each request (query, URL segment, form, attachment, serialized body, header) in a straightforward way +- Serialize the payload to JSON or XML if necessary +- Set the correct content headers (content type, disposition, length, etc) +- Handle the remote endpoint response +- Deserialize the response from JSON or XML if necessary -::: warning -Note that exceptions from `ExecuteAsync` are not thrown but are available in the `ErrorException` property. -::: +As an example, let's look at a simple Twitter API v2 client, which uses OAuth2 machine-to-machine authentication. For it to work, you would need to have access to Twitter Developers portal, an a project, and an approved application inside the project with OAuth2 enabled. + +### Authenticator + +Before we can make any call to the API itself, we need to get a bearer token. Twitter exposes an endpoint `https://api.twitter.com/oauth2/token`. As it follows the OAuth2 conventions, the code can be used to create an authenticator for some other vendors. + +First, we need a model for deserializing the token endpoint response. OAuth2 uses snake case for property naming, so we need to decorate model properties with `JsonPropertyName` attribute: ```csharp -// TwilioApi.cs -public class TwilioApi { - const string BaseUrl = "https://api.twilio.com/2008-08-01"; +record TokenResponse { + [JsonPropertyName("token_type")] + public string TokenType { get; init; } + [JsonPropertyName("access_token")] + public string AccessToken { get; init; } +} +``` - readonly RestClient _client; +Next, we create the authenticator itself. It needs the API key and API key secret for calling the token endpoint using basic HTTP authentication. In addition, we can extend the list of parameters with the base URL, so it can be converted to a more generic OAuth2 authenticator. - string _accountSid; +The easiest way to create an authenticator is to inherit is from the `AuthanticatorBase` base class: - public TwilioApi(string accountSid, string secretKey) { - _client = new RestClient(BaseUrl); - _client.Authenticator = new HttpBasicAuthenticator(accountSid, secretKey); - _client.AddDefaultParameter( - "AccountSid", _accountSid, ParameterType.UrlSegment - ); // used on every request - _accountSid = accountSid; +```csharp +public class TwitterAuthenticator : AuthenticatorBase { + readonly string _baseUrl; + readonly string _clientId; + readonly string _clientSecret; + + public TwitterAuthenticator(string baseUrl, string clientId, string clientSecret) : base("") { + _baseUrl = baseUrl; + _clientId = clientId; + _clientSecret = clientSecret; + } + + protected override async ValueTask GetAuthenticationParameter(string accessToken) { + var token = string.IsNullOrEmpty(Token) ? await GetToken() : Token; + return new HeaderParameter(KnownHeaders.Authorization, token); } } ``` -Next, define a class that maps to the data returned by the API. +During the first call made by the client using the authenticator, it will find out that the `Token` property is empty. It will then call the `GetToken` function to get the token once, and then will reuse the token going forwards. + +Now, we need to include the `GetToken` function to the class: ```csharp -// Call.cs -public class Call { - public string Sid { get; set; } - public DateTime DateCreated { get; set; } - public DateTime DateUpdated { get; set; } - public string CallSegmentSid { get; set; } - public string AccountSid { get; set; } - public string Called { get; set; } - public string Caller { get; set; } - public string PhoneNumberSid { get; set; } - public int Status { get; set; } - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } - public int Duration { get; set; } - public decimal Price { get; set; } - public int Flags { get; set; } +async Task GetToken() { + var options = new RestClientOptions(_baseUrl); + using var client = new RestClient(options) { + Authenticator = new HttpBasicAuthenticator(_clientId, _clientSecret), + }; + + var request = new RestRequest("oauth2/token") + .AddParameter("grant_type", "client_credentials"); + var response = await client.PostAsync(request); + return $"{response!.TokenType} {response!.AccessToken}"; } ``` -Then add a method to query the API for the details of a specific Call resource. +As we need to make a call to the token endpoint, we need our own, short-lived instance of `RestClient`. Unlike the actual Twitter client, it will use the `HttpBasicAuthenticator` to send API key and secret as username and password. The client is then gets disposed as we only use it once. -```csharp -// TwilioApi.cs, GetCall method of TwilioApi class -public Task GetCall(string callSid) { - var request = new RestRequest("Accounts/{AccountSid}/Calls/{CallSid}"); - request.RootElement = "Call"; - request.AddParameter("CallSid", callSid, ParameterType.UrlSegment); +Here we add a POST parameter `grant_type` with `client_credentials` as its value. At the moment, it's the only supported value. + +The POST request will use the `application/x-www-form-urlencoded` content type by default. + +### API client - return _client.GetAsync(request); +Now, we can start creating the API client itself. Here we start with a single function that retrieves one Twitter user. Let's being by defining the API client interface: + +```csharp +public interface ITwitterClient { + Task GetUser(string user); } ``` -There's some magic here that RestSharp takes care of, so you don't have to. +As the function returns a `TwitterUser` instance, we need to define it as a model: + +```csharp +public record TwitterUser(string Id, string Name, string Username); +``` -The API returns XML, which is automatically detected and deserialized to the Call object using the default `XmlDeserializer`. -By default, a call is made via a GET HTTP request. You can change this by setting the `Method` property of `RestRequest` -or specifying the method in the constructor when creating an instance (covered below). -Parameters of type `UrlSegment` have their values injected into the URL based on a matching token name existing in the Resource property value. -`AccountSid` is set in `TwilioApi.Execute` because it is common to every request. -We specify the name of the root element to start deserializing from. In this case, the XML returned is `...` and since the Response element itself does not contain any information relevant to our model, we start the deserializing one step down the tree. +When that is done, we can implement the interface and add all the necessary code blocks to get a working API client. -You can also make POST (and PUT/DELETE/HEAD/OPTIONS) requests: +The client class needs the following: +- A constructor, which accepts API credentials to be passed to the authenticator +- A wrapped `RestClient` instance with Twitter API base URI pre-configured +- The `TwitterAuthenticator` that we created previously as the client authenticator +- The actual function to get the user ```csharp -// TwilioApi.cs, method of TwilioApi class -public Task InitiateOutboundCall(CallOptions options) { - var request = new RestRequest("Accounts/{AccountSid}/Calls") { - RootElement = "Calls" +public class TwitterClient : ITwitterClient, IDisposable { + readonly RestClient _client; + + public TwitterClient(string apiKey, string apiKeySecret) { + var options = new RestClientOptions("https://api.twitter.com/2"); + + _client = new RestClient(options) { + Authenticator = new TwitterAuthenticator("https://api.twitter.com", apiKey, apiKeySecret) + }; } - .AddParameter("Caller", options.Caller) - .AddParameter("Called", options.Called) - .AddParameter("Url", options.Url); - if (options.Method.HasValue) request.AddParameter("Method", options.Method); - if (options.SendDigits.HasValue()) request.AddParameter("SendDigits", options.SendDigits); - if (options.IfMachine.HasValue) request.AddParameter("IfMachine", options.IfMachine.Value); - if (options.Timeout.HasValue) request.AddParameter("Timeout", options.Timeout.Value); + public async Task GetUser(string user) { + var response = await _client.GetJsonAsync>( + "users/by/username/{user}", + new { user } + ); + return response!.Data; + } - return _client.PostAsync(request); + record TwitterSingleObject(T Data); + + public void Dispose() { + _client?.Dispose(); + GC.SuppressFinalize(this); + } } ``` -This example also demonstrates RestSharp's lightweight validation helpers. -These helpers allow you to verify before making the request that the values submitted are valid. -Read more about Validation here. +Couple of things that don't fall to the "basics" list. +- The API client class needs to be disposable, so it can dispose the wrapped `HttpClient` instance +- Twitter API returns wrapped models. In this case we use the `TwitterSingleObject` wrapper, in other methods you'd need a similar object with `T[] Data` to accept collections -All the values added via `AddParameter` in this example will be submitted as a standard encoded form, -similar to a form submission made via a web page. If this were a GET-style request (GET/DELETE/OPTIONS/HEAD), -the parameter values would be submitted via the query string instead. You can also add header and cookie -parameters with `AddParameter`. To add all properties for an object as parameters, use `AddObject`. -To add a file for upload, use `AddFile` (the request will be sent as a multipart encoded form). -To include a request body like XML or JSON, use `AddXmlBody` or `AddJsonBody`. +You can find the full example code in [this gist](https://gist.github.com/alexeyzimarev/62d77bb25d7aa5bb4b9685461f8aabdd). + +Such a client can and should be used _as a singleton_, as it's thread-safe and authentication-aware. If you make it a transient dependency, you'll keep bombarding Twitter with token requests and effectively half your request limit. ## Request Parameters @@ -160,6 +188,15 @@ If you have `GetOrPost` parameters as well, they will overwrite the `RequestBody We recommend using `AddJsonBody` or `AddXmlBody` methods instead of `AddParameter` with type `BodyParameter`. Those methods will set the proper request type and do the serialization work for you. +#### AddStringBody + +If you have a pre-serialized payload like a JSON string, you can use `AddStringBody` to add it as a body parameter. You need to specify the content type, so the remote endpoint knows what to do with the request body. For example: + +```csharp +const json = "{ data: { foo: \"bar\" } }"; +request.AddStringBody(json, ContentType.Json); +``` + #### AddJsonBody When you call `AddJsonBody`, it does the following for you: From 723fe5f8958d2ed763d720843e613ef333399934 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Wed, 19 Jan 2022 21:39:01 +0100 Subject: [PATCH 3/5] Moved test files Serializer detection changes --- RestSharp.sln | 6 ++-- .../JsonNetSerializer.cs | 6 ++-- src/RestSharp/Properties/AssemblyInfo.cs | 2 +- .../Request/HttpContentExtensions.cs | 21 +++++++++++--- .../Request/HttpRequestMessageExtensions.cs | 9 +++--- src/RestSharp/Request/RequestContent.cs | 8 +++--- src/RestSharp/RestClient.Serialization.cs | 26 ++++++++++-------- src/RestSharp/RestClient.cs | 3 +- src/RestSharp/Serializers/ContentType.cs | 6 ++-- src/RestSharp/Serializers/IRestSerializer.cs | 4 ++- .../Json/SystemTextJsonSerializer.cs | 7 +++-- src/RestSharp/Serializers/SerializerRecord.cs | 9 ++++-- .../Serializers/Xml/XmlRestSerializer.cs | 4 ++- .../Assets/Koala.jpg | Bin .../Assets/TestFile.txt | 0 .../Authentication/AuthenticationTests.cs | 4 +-- .../Authentication/OAuth2Tests.cs | 4 +-- .../CompressionTests.cs | 2 +- .../DefaultParameterTests.cs | 4 +-- .../DownloadFileTests.cs | 2 +- .../Fixtures/CaptureFixture.cs | 2 +- .../Fixtures/OutputLogger.cs | 2 +- .../Fixtures/RequestBodyFixture.cs | 2 +- .../Fixtures/TestServer.cs | 2 +- .../HttpHeadersTests.cs | 4 +-- .../Models/LinkedINMemberProfile.cs | 2 +- .../MultipartFormDataTests.cs | 14 +++++----- .../NonProtocolExceptionHandlingTests.cs | 2 +- .../OAuth1Tests.cs | 4 +-- .../ProxyTests.cs | 2 +- .../PutTests.cs | 6 ++-- .../RequestBodyTests.cs | 4 +-- .../RequestFailureTests.cs | 4 +-- .../RequestHeadTests.cs | 4 +-- .../RequestTests.cs | 4 +-- .../ResourceStringParametersTests.cs | 2 +- .../RestSharp.Tests.Integrated.csproj} | 0 .../RootElementTests.cs | 2 +- .../StatusCodeTests.cs | 2 +- .../StructuredSyntaxSuffixTests.cs | 2 +- .../UploadFileTests.cs | 4 +-- .../xunit.runner.json | 0 .../NewtonsoftJsonTests.cs | 2 +- .../RestSharp.Tests.Serializers.Json.csproj} | 0 .../SampleData.cs | 2 +- .../SystemTextJsonTests.cs | 2 +- .../NamespacedXmlTests.cs | 7 +++-- .../RestSharp.Tests.Serializers.Xml.csproj} | 0 .../SampleClasses/BearerToken.cs | 4 ++- .../SampleClasses/BooleanTest.cs | 2 +- .../SampleClasses/ColorWithValue.cs | 4 ++- .../SampleClasses/DeserializeAsTest/misc.cs | 4 ++- .../SampleClasses/EmployeeTracker.cs | 2 +- .../SampleClasses/EnumTest.cs | 2 +- .../SampleClasses/Goodreads.cs | 2 +- .../GoogleWeatherWithAttributes.cs | 4 ++- .../SampleClasses/HeaderAndRows.cs | 4 ++- .../SampleClasses/JsonLists.cs | 2 +- .../SampleClasses/Lastfm.cs | 2 +- .../SampleClasses/ListSamples.cs | 2 +- .../SampleClasses/Oddball.cs | 4 ++- .../SampleClasses/SOUser.cs | 2 +- .../SampleClasses/Struct.cs | 2 +- .../SampleClasses/TwilioCallList.cs | 2 +- .../SampleClasses/eventful.cs | 2 +- .../SampleClasses/foursq.cs | 2 +- .../SampleClasses/googleweather.cs | 2 +- .../SampleClasses/misc.cs | 4 ++- .../SampleClasses/nullables.cs | 2 +- .../SampleClasses/twitter.cs | 4 ++- .../SampleData/Goodreads.xml | 0 .../SampleData/GoodreadsFormatError.xml | 0 .../SampleData/GoogleWeather.xml | 0 .../SampleData/InlineListSample.xml | 0 .../SampleData/Lastfm.xml | 0 .../SampleData/ListWithAttributes.xml | 0 .../SampleData/NestedListSample.xml | 0 .../SampleData/boolean_from_number.xml | 0 .../SampleData/boolean_from_string.xml | 0 .../SampleData/deserialize_as_list.xml | 0 .../SampleData/directlists.xml | 0 .../SampleData/eventful.xml | 0 .../SampleData/header_and_rows.xml | 0 .../SampleData/restsharp.nuspec | 0 .../SampleData/xmllists.xml | 0 .../XmlAttributeDeserializerTests.cs | 5 ++-- .../XmlDeserializerTests.cs | 7 +++-- .../XmlSerializerTests.cs | 6 ++-- 88 files changed, 170 insertions(+), 118 deletions(-) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Assets/Koala.jpg (100%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Assets/TestFile.txt (100%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Authentication/AuthenticationTests.cs (92%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Authentication/OAuth2Tests.cs (88%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/CompressionTests.cs (98%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/DefaultParameterTests.cs (96%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/DownloadFileTests.cs (98%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Fixtures/CaptureFixture.cs (92%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Fixtures/OutputLogger.cs (83%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Fixtures/RequestBodyFixture.cs (86%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Fixtures/TestServer.cs (98%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/HttpHeadersTests.cs (91%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/Models/LinkedINMemberProfile.cs (87%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/MultipartFormDataTests.cs (93%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/NonProtocolExceptionHandlingTests.cs (98%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/OAuth1Tests.cs (99%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/ProxyTests.cs (94%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/PutTests.cs (91%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/RequestBodyTests.cs (98%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/RequestFailureTests.cs (95%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/RequestHeadTests.cs (97%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/RequestTests.cs (96%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/ResourceStringParametersTests.cs (96%) rename test/{RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj => RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj} (100%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/RootElementTests.cs (96%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/StatusCodeTests.cs (99%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/StructuredSyntaxSuffixTests.cs (98%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/UploadFileTests.cs (95%) rename test/{RestSharp.IntegrationTests => RestSharp.Tests.Integrated}/xunit.runner.json (100%) rename test/{RestSharp.Serializers.Json.Tests => RestSharp.Tests.Serializers.Json}/NewtonsoftJsonTests.cs (98%) rename test/{RestSharp.Serializers.Json.Tests/RestSharp.Serializers.Json.Tests.csproj => RestSharp.Tests.Serializers.Json/RestSharp.Tests.Serializers.Json.csproj} (100%) rename test/{RestSharp.Serializers.Json.Tests => RestSharp.Tests.Serializers.Json}/SampleData.cs (87%) rename test/{RestSharp.Serializers.Json.Tests => RestSharp.Tests.Serializers.Json}/SystemTextJsonTests.cs (97%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/NamespacedXmlTests.cs (98%) rename test/{RestSharp.Serializers.Xml.Tests/RestSharp.Serializers.Xml.Tests.csproj => RestSharp.Tests.Serializers.Xml/RestSharp.Tests.Serializers.Xml.csproj} (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/BearerToken.cs (80%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/BooleanTest.cs (52%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/ColorWithValue.cs (59%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/DeserializeAsTest/misc.cs (70%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/EmployeeTracker.cs (92%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/EnumTest.cs (94%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/Goodreads.cs (86%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/GoogleWeatherWithAttributes.cs (94%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/HeaderAndRows.cs (77%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/JsonLists.cs (65%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/Lastfm.cs (93%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/ListSamples.cs (92%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/Oddball.cs (79%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/SOUser.cs (89%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/Struct.cs (69%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/TwilioCallList.cs (74%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/eventful.cs (97%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/foursq.cs (69%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/googleweather.cs (95%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/misc.cs (98%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/nullables.cs (71%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleClasses/twitter.cs (96%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/Goodreads.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/GoodreadsFormatError.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/GoogleWeather.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/InlineListSample.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/Lastfm.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/ListWithAttributes.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/NestedListSample.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/boolean_from_number.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/boolean_from_string.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/deserialize_as_list.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/directlists.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/eventful.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/header_and_rows.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/restsharp.nuspec (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/SampleData/xmllists.xml (100%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/XmlAttributeDeserializerTests.cs (99%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/XmlDeserializerTests.cs (99%) rename test/{RestSharp.Serializers.Xml.Tests => RestSharp.Tests.Serializers.Xml}/XmlSerializerTests.cs (99%) diff --git a/RestSharp.sln b/RestSharp.sln index 2f893b3ac..2b38a8b2f 100644 --- a/RestSharp.sln +++ b/RestSharp.sln @@ -9,7 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9051DDA0 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Tests", "test\RestSharp.Tests\RestSharp.Tests.csproj", "{B1C55C9B-3287-4EB2-8ADD-795DBC77013D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.IntegrationTests", "test\RestSharp.IntegrationTests\RestSharp.IntegrationTests.csproj", "{AC3B3DDC-F011-4E19-8C9B-F748B19ED3C0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Tests.Integrated", "test\RestSharp.Tests.Integrated\RestSharp.Tests.Integrated.csproj", "{AC3B3DDC-F011-4E19-8C9B-F748B19ED3C0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Serializers.NewtonsoftJson", "src\RestSharp.Serializers.NewtonsoftJson\RestSharp.Serializers.NewtonsoftJson.csproj", "{4205A187-9732-4DA8-B0BE-77A2C6B8C6A1}" EndProject @@ -17,7 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serializers", "Serializers" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Tests.Shared", "test\RestSharp.Tests.Shared\RestSharp.Tests.Shared.csproj", "{73896669-F05C-41AC-9F6F-A11F549EDEDC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Serializers.Json.Tests", "test\RestSharp.Serializers.Json.Tests\RestSharp.Serializers.Json.Tests.csproj", "{8BF81225-2F85-4412-AD18-6579CBA1879B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Tests.Serializers.Json", "test\RestSharp.Tests.Serializers.Json\RestSharp.Tests.Serializers.Json.csproj", "{8BF81225-2F85-4412-AD18-6579CBA1879B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Perf", "Perf", "{1C42C435-8826-4044-8775-A1DA40EF4866}" EndProject @@ -25,7 +25,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Benchmarks", "ben EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.InteractiveTests", "test\RestSharp.InteractiveTests\RestSharp.InteractiveTests.csproj", "{6D7D1D60-4473-4C52-800C-9B892C6640A5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Serializers.Xml.Tests", "test\RestSharp.Serializers.Xml.Tests\RestSharp.Serializers.Xml.Tests.csproj", "{E6D94C12-9AD7-46E6-AB62-3676F25FDE51}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Tests.Serializers.Xml", "test\RestSharp.Tests.Serializers.Xml\RestSharp.Tests.Serializers.Xml.csproj", "{E6D94C12-9AD7-46E6-AB62-3676F25FDE51}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RestSharp.Serializers.Xml", "src\RestSharp.Serializers.Xml\RestSharp.Serializers.Xml.csproj", "{4A35B1C5-520D-4267-BA70-2DCEAC0A5662}" EndProject diff --git a/src/RestSharp.Serializers.NewtonsoftJson/JsonNetSerializer.cs b/src/RestSharp.Serializers.NewtonsoftJson/JsonNetSerializer.cs index bcb09818e..00101952a 100644 --- a/src/RestSharp.Serializers.NewtonsoftJson/JsonNetSerializer.cs +++ b/src/RestSharp.Serializers.NewtonsoftJson/JsonNetSerializer.cs @@ -73,11 +73,11 @@ public class JsonNetSerializer : IRestSerializer, ISerializer, IDeserializer { public ISerializer Serializer => this; public IDeserializer Deserializer => this; - public string[] SupportedContentTypes { get; } = { - "application/json", "text/json", "text/x-json", "text/javascript", "*+json" - }; + public string[] AcceptedContentTypes => Serializers.ContentType.JsonAccept; public string ContentType { get; set; } = "application/json"; + public SupportsContentType SupportsContentType => contentType => contentType.Contains("json"); + public DataFormat DataFormat => DataFormat.Json; } \ No newline at end of file diff --git a/src/RestSharp/Properties/AssemblyInfo.cs b/src/RestSharp/Properties/AssemblyInfo.cs index cf7b969d5..08b227485 100644 --- a/src/RestSharp/Properties/AssemblyInfo.cs +++ b/src/RestSharp/Properties/AssemblyInfo.cs @@ -2,7 +2,7 @@ [assembly: InternalsVisibleTo( - "RestSharp.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100fda57af14a288d46e3efea89617037585c4de57159cd536ca6dff792ea1d6addc665f2fccb4285413d9d44db5a1be87cb82686db200d16325ed9c42c89cd4824d8cc447f7cee2ac000924c3bceeb1b7fcb5cc1a3901785964d48ce14172001084134f4dcd9973c3776713b595443b1064bb53e2eeb924969244d354e46495e9d" + "RestSharp.Tests.Integrated, PublicKey=0024000004800000940000000602000000240000525341310004000001000100fda57af14a288d46e3efea89617037585c4de57159cd536ca6dff792ea1d6addc665f2fccb4285413d9d44db5a1be87cb82686db200d16325ed9c42c89cd4824d8cc447f7cee2ac000924c3bceeb1b7fcb5cc1a3901785964d48ce14172001084134f4dcd9973c3776713b595443b1064bb53e2eeb924969244d354e46495e9d" ), InternalsVisibleTo( "RestSharp.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100fda57af14a288d46e3efea89617037585c4de57159cd536ca6dff792ea1d6addc665f2fccb4285413d9d44db5a1be87cb82686db200d16325ed9c42c89cd4824d8cc447f7cee2ac000924c3bceeb1b7fcb5cc1a3901785964d48ce14172001084134f4dcd9973c3776713b595443b1064bb53e2eeb924969244d354e46495e9d" diff --git a/src/RestSharp/Request/HttpContentExtensions.cs b/src/RestSharp/Request/HttpContentExtensions.cs index 0a9d7f6e2..99f1ed7f5 100644 --- a/src/RestSharp/Request/HttpContentExtensions.cs +++ b/src/RestSharp/Request/HttpContentExtensions.cs @@ -13,17 +13,30 @@ // limitations under the License. // -namespace RestSharp; +using System.Linq.Expressions; + +namespace RestSharp; public static class HttpContentExtensions { - public static string GetFormBoundary(this HttpContent content) { + static readonly Func GetBoundary = GetFieldAccessor("_boundary"); + + public static string GetFormBoundary(this MultipartFormDataContent content) { + return GetBoundary(content); var contentType = content.Headers.ContentType?.ToString(); var index = contentType?.IndexOf("boundary=", StringComparison.Ordinal) ?? 0; return index > 0 ? GetFormBoundary(contentType!, index) : ""; - } - + } + static string GetFormBoundary(string headerValue, int index) { var part = headerValue.Substring(index); return part.Substring(10, 36); } + + static Func GetFieldAccessor(string fieldName) { + var param = Expression.Parameter(typeof(T), "arg"); + var member = Expression.Field(param, fieldName); + var lambda = Expression.Lambda(typeof(Func), member, param); + var compiled = (Func)lambda.Compile(); + return compiled; + } } \ No newline at end of file diff --git a/src/RestSharp/Request/HttpRequestMessageExtensions.cs b/src/RestSharp/Request/HttpRequestMessageExtensions.cs index 0276fceaf..3a5974d76 100644 --- a/src/RestSharp/Request/HttpRequestMessageExtensions.cs +++ b/src/RestSharp/Request/HttpRequestMessageExtensions.cs @@ -13,6 +13,7 @@ // limitations under the License. // +using System.Net.Http.Headers; using RestSharp.Extensions; namespace RestSharp; @@ -21,13 +22,13 @@ static class HttpRequestMessageExtensions { public static void AddHeaders(this HttpRequestMessage message, RequestHeaders headers) { var headerParameters = headers.Parameters.Where(x => !RequestContent.ContentHeaders.Contains(x.Name)); - headerParameters.ForEach(AddHeader); + headerParameters.ForEach(x => AddHeader(x, message.Headers)); - void AddHeader(Parameter parameter) { + void AddHeader(Parameter parameter, HttpHeaders httpHeaders) { var parameterStringValue = parameter.Value!.ToString(); - message.Headers.Remove(parameter.Name!); - message.Headers.TryAddWithoutValidation(parameter.Name!, parameterStringValue); + httpHeaders.Remove(parameter.Name!); + httpHeaders.TryAddWithoutValidation(parameter.Name!, parameterStringValue); } } } \ No newline at end of file diff --git a/src/RestSharp/Request/RequestContent.cs b/src/RestSharp/Request/RequestContent.cs index f5575babe..c1b152973 100644 --- a/src/RestSharp/Request/RequestContent.cs +++ b/src/RestSharp/Request/RequestContent.cs @@ -185,10 +185,10 @@ void AddHeader(Parameter parameter) { } } - string GetContentTypeHeader(string contentType) { - var boundary = Content!.GetFormBoundary(); - return boundary.IsEmpty() ? contentType : $"{contentType}; boundary=\"{boundary}\""; - } + string GetContentTypeHeader(string contentType) + => Content is MultipartFormDataContent mpContent + ? $"{contentType}; boundary=\"{mpContent.GetFormBoundary()}\"" + : contentType; public void Dispose() { _streams.ForEach(x => x.Dispose()); diff --git a/src/RestSharp/RestClient.Serialization.cs b/src/RestSharp/RestClient.Serialization.cs index 5e3005973..539689ea4 100644 --- a/src/RestSharp/RestClient.Serialization.cs +++ b/src/RestSharp/RestClient.Serialization.cs @@ -31,11 +31,17 @@ public partial class RestClient { /// Function that returns the serializer instance public RestClient UseSerializer(Func serializerFactory) { var instance = serializerFactory(); - Serializers[instance.DataFormat] = new SerializerRecord(instance.DataFormat, instance.SupportedContentTypes, serializerFactory); + + Serializers[instance.DataFormat] = new SerializerRecord( + instance.DataFormat, + instance.AcceptedContentTypes, + instance.SupportsContentType, + serializerFactory + ); AssignAcceptedContentTypes(); return this; } - + public void UseDefaultSerializers() => UseSerializer().UseSerializer(); /// @@ -58,7 +64,7 @@ internal RestResponse Deserialize(RestRequest request, RestResponse raw) { // Only continue if there is a handler defined else there is no way to deserialize the data. // This can happen when a request returns for example a 404 page instead of the requested JSON/XML resource var handler = GetContentDeserializer(raw, request.RequestFormat); - + if (handler is IXmlDeserializer xml && request is RestXmlRequest xmlRequest) { if (xmlRequest.XmlNamespace.IsNotEmpty()) xml.Namespace = xmlRequest.XmlNamespace!; @@ -86,16 +92,14 @@ internal RestResponse Deserialize(RestRequest request, RestResponse raw) { } IDeserializer? GetContentDeserializer(RestResponseBase response, DataFormat requestFormat) { - var contentType = response.ContentType != null && AcceptedContentTypes.Contains(response.ContentType) - ? response.ContentType - : DetectContentType(); - if (contentType.IsEmpty()) return null; + if (response.ContentType == null) return null; - var serializer = Serializers.FirstOrDefault(x => x.Value.SupportedContentTypes.Contains(contentType)); - var factory = serializer.Value ?? (Serializers.ContainsKey(requestFormat) ? Serializers[requestFormat] : null); + var serializer = Serializers.Values.FirstOrDefault(x => x.SupportsContentType(response.ContentType)); + var factory = serializer ?? (Serializers.ContainsKey(requestFormat) ? Serializers[requestFormat] : null); return factory?.GetSerializer().Deserializer; - + string? DetectContentType() - => response.Content!.StartsWith("<") ? ContentType.Xml : response.Content.StartsWith("{") ? ContentType.Json : null; + => response.Content!.StartsWith("<") ? ContentType.Xml + : response.Content.StartsWith("{") ? ContentType.Json : null; } } \ No newline at end of file diff --git a/src/RestSharp/RestClient.cs b/src/RestSharp/RestClient.cs index 96f9e4d05..bece3ecd7 100644 --- a/src/RestSharp/RestClient.cs +++ b/src/RestSharp/RestClient.cs @@ -183,7 +183,7 @@ internal Uri BuildUriWithoutQueryParameters(RestRequest request) { } internal void AssignAcceptedContentTypes() - => AcceptedContentTypes = Serializers.SelectMany(x => x.Value.SupportedContentTypes).Distinct().ToArray(); + => AcceptedContentTypes = Serializers.SelectMany(x => x.Value.AcceptedContentTypes).Distinct().ToArray(); void DoBuildUriValidations(RestRequest request) { if (Options.BaseUrl == null && !request.Resource.ToLowerInvariant().StartsWith("http")) @@ -195,6 +195,7 @@ void DoBuildUriValidations(RestRequest request) { public void Dispose() { if (_disposeHttpClient) HttpClient.Dispose(); + GC.SuppressFinalize(this); } readonly bool _disposeHttpClient; diff --git a/src/RestSharp/Serializers/ContentType.cs b/src/RestSharp/Serializers/ContentType.cs index 01259a4cb..798b37971 100644 --- a/src/RestSharp/Serializers/ContentType.cs +++ b/src/RestSharp/Serializers/ContentType.cs @@ -14,6 +14,8 @@ namespace RestSharp.Serializers; +public delegate bool SupportsContentType(string contentType); + public static class ContentType { public const string Json = "application/json"; public const string Xml = "application/xml"; @@ -30,10 +32,10 @@ public static class ContentType { }; public static readonly string[] JsonAccept = { - "application/json", "text/json", "text/x-json", "text/javascript", "*+json" + "application/json", "text/json", "text/x-json", "text/javascript" }; public static readonly string[] XmlAccept = { - "application/xml", "text/xml", "*+xml", "*" + "application/xml", "text/xml" }; } \ No newline at end of file diff --git a/src/RestSharp/Serializers/IRestSerializer.cs b/src/RestSharp/Serializers/IRestSerializer.cs index 2a8e7f3d5..e4777857a 100644 --- a/src/RestSharp/Serializers/IRestSerializer.cs +++ b/src/RestSharp/Serializers/IRestSerializer.cs @@ -18,7 +18,9 @@ public interface IRestSerializer { ISerializer Serializer { get; } IDeserializer Deserializer { get; } - string[] SupportedContentTypes { get; } + string[] AcceptedContentTypes { get; } + + SupportsContentType SupportsContentType { get; } DataFormat DataFormat { get; } diff --git a/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs b/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs index 2fb5c3aa9..142d3bf8c 100644 --- a/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs +++ b/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs @@ -38,11 +38,12 @@ public class SystemTextJsonSerializer : IRestSerializer, ISerializer, IDeseriali public ISerializer Serializer => this; public IDeserializer Deserializer => this; - public string[] SupportedContentTypes { get; } = { - "application/json", "text/json", "text/x-json", "text/javascript", "*+json" - }; + + public string[] AcceptedContentTypes => Serializers.ContentType.JsonAccept; public string ContentType { get; set; } = "application/json"; + public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("json"); + public DataFormat DataFormat => DataFormat.Json; } \ No newline at end of file diff --git a/src/RestSharp/Serializers/SerializerRecord.cs b/src/RestSharp/Serializers/SerializerRecord.cs index 6fc5182fa..faee107b1 100644 --- a/src/RestSharp/Serializers/SerializerRecord.cs +++ b/src/RestSharp/Serializers/SerializerRecord.cs @@ -12,6 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace RestSharp.Serializers; +namespace RestSharp.Serializers; -public record SerializerRecord(DataFormat DataFormat, string[] SupportedContentTypes, Func GetSerializer); \ No newline at end of file +public record SerializerRecord( + DataFormat DataFormat, + string[] AcceptedContentTypes, + SupportsContentType SupportsContentType, + Func GetSerializer +); \ No newline at end of file diff --git a/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs b/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs index 41b3b4dba..31a9b84e6 100644 --- a/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs +++ b/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs @@ -27,7 +27,9 @@ public XmlRestSerializer(IXmlSerializer xmlSerializer, IXmlDeserializer xmlDeser public ISerializer Serializer => _xmlSerializer; public IDeserializer Deserializer => _xmlDeserializer; - public string[] SupportedContentTypes => ContentType.XmlAccept; + public string[] AcceptedContentTypes => ContentType.XmlAccept; + + public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("xml"); public DataFormat DataFormat => DataFormat.Xml; diff --git a/test/RestSharp.IntegrationTests/Assets/Koala.jpg b/test/RestSharp.Tests.Integrated/Assets/Koala.jpg similarity index 100% rename from test/RestSharp.IntegrationTests/Assets/Koala.jpg rename to test/RestSharp.Tests.Integrated/Assets/Koala.jpg diff --git a/test/RestSharp.IntegrationTests/Assets/TestFile.txt b/test/RestSharp.Tests.Integrated/Assets/TestFile.txt similarity index 100% rename from test/RestSharp.IntegrationTests/Assets/TestFile.txt rename to test/RestSharp.Tests.Integrated/Assets/TestFile.txt diff --git a/test/RestSharp.IntegrationTests/Authentication/AuthenticationTests.cs b/test/RestSharp.Tests.Integrated/Authentication/AuthenticationTests.cs similarity index 92% rename from test/RestSharp.IntegrationTests/Authentication/AuthenticationTests.cs rename to test/RestSharp.Tests.Integrated/Authentication/AuthenticationTests.cs index 3eaf45676..18c7246e6 100644 --- a/test/RestSharp.IntegrationTests/Authentication/AuthenticationTests.cs +++ b/test/RestSharp.Tests.Integrated/Authentication/AuthenticationTests.cs @@ -1,9 +1,9 @@ using System.Text; using System.Web; using RestSharp.Authenticators; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; -namespace RestSharp.IntegrationTests.Authentication; +namespace RestSharp.Tests.Integrated.Authentication; [Collection(nameof(TestServerCollection))] public class AuthenticationTests { diff --git a/test/RestSharp.IntegrationTests/Authentication/OAuth2Tests.cs b/test/RestSharp.Tests.Integrated/Authentication/OAuth2Tests.cs similarity index 88% rename from test/RestSharp.IntegrationTests/Authentication/OAuth2Tests.cs rename to test/RestSharp.Tests.Integrated/Authentication/OAuth2Tests.cs index 51750c25d..6ff4e4a99 100644 --- a/test/RestSharp.IntegrationTests/Authentication/OAuth2Tests.cs +++ b/test/RestSharp.Tests.Integrated/Authentication/OAuth2Tests.cs @@ -1,7 +1,7 @@ using RestSharp.Authenticators.OAuth2; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; -namespace RestSharp.IntegrationTests.Authentication; +namespace RestSharp.Tests.Integrated.Authentication; [Collection(nameof(TestServerCollection))] public class OAuth2Tests { diff --git a/test/RestSharp.IntegrationTests/CompressionTests.cs b/test/RestSharp.Tests.Integrated/CompressionTests.cs similarity index 98% rename from test/RestSharp.IntegrationTests/CompressionTests.cs rename to test/RestSharp.Tests.Integrated/CompressionTests.cs index 8ef9cf1eb..2d03cb9ab 100644 --- a/test/RestSharp.IntegrationTests/CompressionTests.cs +++ b/test/RestSharp.Tests.Integrated/CompressionTests.cs @@ -3,7 +3,7 @@ using RestSharp.Tests.Shared.Extensions; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class CompressionTests { readonly ITestOutputHelper _output; diff --git a/test/RestSharp.IntegrationTests/DefaultParameterTests.cs b/test/RestSharp.Tests.Integrated/DefaultParameterTests.cs similarity index 96% rename from test/RestSharp.IntegrationTests/DefaultParameterTests.cs rename to test/RestSharp.Tests.Integrated/DefaultParameterTests.cs index 303b72981..b0b8d3aa9 100644 --- a/test/RestSharp.IntegrationTests/DefaultParameterTests.cs +++ b/test/RestSharp.Tests.Integrated/DefaultParameterTests.cs @@ -1,8 +1,8 @@ using System.Net; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; [Collection(nameof(TestServerCollection))] public class DefaultParameterTests : IDisposable { diff --git a/test/RestSharp.IntegrationTests/DownloadFileTests.cs b/test/RestSharp.Tests.Integrated/DownloadFileTests.cs similarity index 98% rename from test/RestSharp.IntegrationTests/DownloadFileTests.cs rename to test/RestSharp.Tests.Integrated/DownloadFileTests.cs index bdb4299cd..fe7a2fde3 100644 --- a/test/RestSharp.IntegrationTests/DownloadFileTests.cs +++ b/test/RestSharp.Tests.Integrated/DownloadFileTests.cs @@ -2,7 +2,7 @@ using System.Text; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public sealed class DownloadFileTests : IDisposable { public DownloadFileTests() { diff --git a/test/RestSharp.IntegrationTests/Fixtures/CaptureFixture.cs b/test/RestSharp.Tests.Integrated/Fixtures/CaptureFixture.cs similarity index 92% rename from test/RestSharp.IntegrationTests/Fixtures/CaptureFixture.cs rename to test/RestSharp.Tests.Integrated/Fixtures/CaptureFixture.cs index 55def734e..fe488b3a5 100644 --- a/test/RestSharp.IntegrationTests/Fixtures/CaptureFixture.cs +++ b/test/RestSharp.Tests.Integrated/Fixtures/CaptureFixture.cs @@ -1,7 +1,7 @@ using System.Collections.Specialized; using System.Net; -namespace RestSharp.IntegrationTests.Fixtures; +namespace RestSharp.Tests.Integrated.Fixtures; public class CaptureFixture { diff --git a/test/RestSharp.IntegrationTests/Fixtures/OutputLogger.cs b/test/RestSharp.Tests.Integrated/Fixtures/OutputLogger.cs similarity index 83% rename from test/RestSharp.IntegrationTests/Fixtures/OutputLogger.cs rename to test/RestSharp.Tests.Integrated/Fixtures/OutputLogger.cs index 69f868862..f82dfbe83 100644 --- a/test/RestSharp.IntegrationTests/Fixtures/OutputLogger.cs +++ b/test/RestSharp.Tests.Integrated/Fixtures/OutputLogger.cs @@ -1,6 +1,6 @@ using HttpTracer.Logger; -namespace RestSharp.IntegrationTests.Fixtures; +namespace RestSharp.Tests.Integrated.Fixtures; public class OutputLogger : ILogger{ readonly ITestOutputHelper _output; diff --git a/test/RestSharp.IntegrationTests/Fixtures/RequestBodyFixture.cs b/test/RestSharp.Tests.Integrated/Fixtures/RequestBodyFixture.cs similarity index 86% rename from test/RestSharp.IntegrationTests/Fixtures/RequestBodyFixture.cs rename to test/RestSharp.Tests.Integrated/Fixtures/RequestBodyFixture.cs index 82a5d874f..367563729 100644 --- a/test/RestSharp.IntegrationTests/Fixtures/RequestBodyFixture.cs +++ b/test/RestSharp.Tests.Integrated/Fixtures/RequestBodyFixture.cs @@ -1,6 +1,6 @@ using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests.Fixtures; +namespace RestSharp.Tests.Integrated.Fixtures; public sealed class RequestBodyFixture : IDisposable { public SimpleServer Server { get; } diff --git a/test/RestSharp.IntegrationTests/Fixtures/TestServer.cs b/test/RestSharp.Tests.Integrated/Fixtures/TestServer.cs similarity index 98% rename from test/RestSharp.IntegrationTests/Fixtures/TestServer.cs rename to test/RestSharp.Tests.Integrated/Fixtures/TestServer.cs index 59cf3cdc4..020e29c0d 100644 --- a/test/RestSharp.IntegrationTests/Fixtures/TestServer.cs +++ b/test/RestSharp.Tests.Integrated/Fixtures/TestServer.cs @@ -8,7 +8,7 @@ using RestSharp.Extensions; using RestSharp.Tests.Shared.Extensions; -namespace RestSharp.IntegrationTests.Fixtures; +namespace RestSharp.Tests.Integrated.Fixtures; public class TestServerFixture : IAsyncLifetime { public HttpServer Server { get; } = new(); diff --git a/test/RestSharp.IntegrationTests/HttpHeadersTests.cs b/test/RestSharp.Tests.Integrated/HttpHeadersTests.cs similarity index 91% rename from test/RestSharp.IntegrationTests/HttpHeadersTests.cs rename to test/RestSharp.Tests.Integrated/HttpHeadersTests.cs index e829f0d54..0e19c5d38 100644 --- a/test/RestSharp.IntegrationTests/HttpHeadersTests.cs +++ b/test/RestSharp.Tests.Integrated/HttpHeadersTests.cs @@ -1,7 +1,7 @@ -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class HttpHeadersTests : CaptureFixture { readonly ITestOutputHelper _output; diff --git a/test/RestSharp.IntegrationTests/Models/LinkedINMemberProfile.cs b/test/RestSharp.Tests.Integrated/Models/LinkedINMemberProfile.cs similarity index 87% rename from test/RestSharp.IntegrationTests/Models/LinkedINMemberProfile.cs rename to test/RestSharp.Tests.Integrated/Models/LinkedINMemberProfile.cs index f883f1014..758ff77d3 100644 --- a/test/RestSharp.IntegrationTests/Models/LinkedINMemberProfile.cs +++ b/test/RestSharp.Tests.Integrated/Models/LinkedINMemberProfile.cs @@ -1,4 +1,4 @@ -namespace RestSharp.IntegrationTests.Models; +namespace RestSharp.Tests.Integrated.Models; /// /// Model for used by the LinkedIN integration tests. diff --git a/test/RestSharp.IntegrationTests/MultipartFormDataTests.cs b/test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs similarity index 93% rename from test/RestSharp.IntegrationTests/MultipartFormDataTests.cs rename to test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs index ef43c656b..883372395 100644 --- a/test/RestSharp.IntegrationTests/MultipartFormDataTests.cs +++ b/test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs @@ -1,9 +1,9 @@ using System.Net; using HttpTracer; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public sealed class MultipartFormDataTests : IDisposable { readonly ITestOutputHelper _output; @@ -86,7 +86,7 @@ public async Task MultipartFormData() { string boundary = null; request.OnBeforeRequest = http => { - boundary = http.Content!.GetFormBoundary(); + boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary(); return default; }; @@ -111,7 +111,7 @@ public async Task MultipartFormData_HasDefaultContentType() { string boundary = null; request.OnBeforeRequest = http => { - boundary = http.Content!.GetFormBoundary(); + boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary(); return default; }; @@ -140,7 +140,7 @@ public async Task MultipartFormData_WithCustomContentType() { string boundary = null; request.OnBeforeRequest = http => { - boundary = http.Content!.GetFormBoundary(); + boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary(); return default; }; @@ -166,7 +166,7 @@ public async Task MultipartFormData_WithParameterAndFile_Async() { string boundary = null; request.OnBeforeRequest = http => { - boundary = http.Content!.GetFormBoundary(); + boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary(); return default; }; @@ -186,7 +186,7 @@ public async Task MultipartFormDataAsync() { string boundary = null; request.OnBeforeRequest = http => { - boundary = http.Content!.GetFormBoundary(); + boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary(); return default; }; diff --git a/test/RestSharp.IntegrationTests/NonProtocolExceptionHandlingTests.cs b/test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs similarity index 98% rename from test/RestSharp.IntegrationTests/NonProtocolExceptionHandlingTests.cs rename to test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs index 79c7455c1..74bfb4f65 100644 --- a/test/RestSharp.IntegrationTests/NonProtocolExceptionHandlingTests.cs +++ b/test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs @@ -1,7 +1,7 @@ using System.Net; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public sealed class NonProtocolExceptionHandlingTests : IDisposable { // ReSharper disable once ClassNeverInstantiated.Local diff --git a/test/RestSharp.IntegrationTests/OAuth1Tests.cs b/test/RestSharp.Tests.Integrated/OAuth1Tests.cs similarity index 99% rename from test/RestSharp.IntegrationTests/OAuth1Tests.cs rename to test/RestSharp.Tests.Integrated/OAuth1Tests.cs index 40c531a16..504f9bf81 100644 --- a/test/RestSharp.IntegrationTests/OAuth1Tests.cs +++ b/test/RestSharp.Tests.Integrated/OAuth1Tests.cs @@ -3,10 +3,10 @@ using System.Xml.Serialization; using RestSharp.Authenticators; using RestSharp.Authenticators.OAuth; -using RestSharp.IntegrationTests.Models; +using RestSharp.Tests.Integrated.Models; using RestSharp.Tests.Shared.Extensions; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class OAuth1Tests { [XmlRoot("queue")] diff --git a/test/RestSharp.IntegrationTests/ProxyTests.cs b/test/RestSharp.Tests.Integrated/ProxyTests.cs similarity index 94% rename from test/RestSharp.IntegrationTests/ProxyTests.cs rename to test/RestSharp.Tests.Integrated/ProxyTests.cs index f9676bacf..3df18cf82 100644 --- a/test/RestSharp.IntegrationTests/ProxyTests.cs +++ b/test/RestSharp.Tests.Integrated/ProxyTests.cs @@ -1,7 +1,7 @@ using System.Net; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class ProxyTests { // [Fact(Skip = "Behaves strangely on Windows")] diff --git a/test/RestSharp.IntegrationTests/PutTests.cs b/test/RestSharp.Tests.Integrated/PutTests.cs similarity index 91% rename from test/RestSharp.IntegrationTests/PutTests.cs rename to test/RestSharp.Tests.Integrated/PutTests.cs index 2c0dcbdaa..b546e5932 100644 --- a/test/RestSharp.IntegrationTests/PutTests.cs +++ b/test/RestSharp.Tests.Integrated/PutTests.cs @@ -1,8 +1,8 @@ using System.Text.Json; -using RestSharp.IntegrationTests.Fixtures; -using static RestSharp.IntegrationTests.Fixtures.HttpServer; +using RestSharp.Tests.Integrated.Fixtures; +using static RestSharp.Tests.Integrated.Fixtures.HttpServer; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; [Collection(nameof(TestServerCollection))] public class PutTests { diff --git a/test/RestSharp.IntegrationTests/RequestBodyTests.cs b/test/RestSharp.Tests.Integrated/RequestBodyTests.cs similarity index 98% rename from test/RestSharp.IntegrationTests/RequestBodyTests.cs rename to test/RestSharp.Tests.Integrated/RequestBodyTests.cs index 5f69bcf50..41f9181f1 100644 --- a/test/RestSharp.IntegrationTests/RequestBodyTests.cs +++ b/test/RestSharp.Tests.Integrated/RequestBodyTests.cs @@ -1,7 +1,7 @@ -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class RequestBodyTests : IClassFixture { readonly ITestOutputHelper _output; diff --git a/test/RestSharp.IntegrationTests/RequestFailureTests.cs b/test/RestSharp.Tests.Integrated/RequestFailureTests.cs similarity index 95% rename from test/RestSharp.IntegrationTests/RequestFailureTests.cs rename to test/RestSharp.Tests.Integrated/RequestFailureTests.cs index 5493d135e..6b19c0686 100644 --- a/test/RestSharp.IntegrationTests/RequestFailureTests.cs +++ b/test/RestSharp.Tests.Integrated/RequestFailureTests.cs @@ -1,7 +1,7 @@ using System.Net; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; [Collection(nameof(TestServerCollection))] public class RequestFailureTests { diff --git a/test/RestSharp.IntegrationTests/RequestHeadTests.cs b/test/RestSharp.Tests.Integrated/RequestHeadTests.cs similarity index 97% rename from test/RestSharp.IntegrationTests/RequestHeadTests.cs rename to test/RestSharp.Tests.Integrated/RequestHeadTests.cs index 6398e0798..a69cc5b9b 100644 --- a/test/RestSharp.IntegrationTests/RequestHeadTests.cs +++ b/test/RestSharp.Tests.Integrated/RequestHeadTests.cs @@ -1,8 +1,8 @@ using System.Net; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class RequestHeadTests : CaptureFixture { [Fact] diff --git a/test/RestSharp.IntegrationTests/RequestTests.cs b/test/RestSharp.Tests.Integrated/RequestTests.cs similarity index 96% rename from test/RestSharp.IntegrationTests/RequestTests.cs rename to test/RestSharp.Tests.Integrated/RequestTests.cs index 5045639d4..fcc0f642f 100644 --- a/test/RestSharp.IntegrationTests/RequestTests.cs +++ b/test/RestSharp.Tests.Integrated/RequestTests.cs @@ -1,7 +1,7 @@ using System.Net; -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; [Collection(nameof(TestServerCollection))] public class AsyncTests { diff --git a/test/RestSharp.IntegrationTests/ResourceStringParametersTests.cs b/test/RestSharp.Tests.Integrated/ResourceStringParametersTests.cs similarity index 96% rename from test/RestSharp.IntegrationTests/ResourceStringParametersTests.cs rename to test/RestSharp.Tests.Integrated/ResourceStringParametersTests.cs index eecbf6ccd..4baf0c280 100644 --- a/test/RestSharp.IntegrationTests/ResourceStringParametersTests.cs +++ b/test/RestSharp.Tests.Integrated/ResourceStringParametersTests.cs @@ -1,7 +1,7 @@ using System.Net; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public sealed class ResourceStringParametersTests : IDisposable { readonly SimpleServer _server; diff --git a/test/RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj b/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj similarity index 100% rename from test/RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj rename to test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj diff --git a/test/RestSharp.IntegrationTests/RootElementTests.cs b/test/RestSharp.Tests.Integrated/RootElementTests.cs similarity index 96% rename from test/RestSharp.IntegrationTests/RootElementTests.cs rename to test/RestSharp.Tests.Integrated/RootElementTests.cs index 89a644553..3aa68abb6 100644 --- a/test/RestSharp.IntegrationTests/RootElementTests.cs +++ b/test/RestSharp.Tests.Integrated/RootElementTests.cs @@ -3,7 +3,7 @@ using RestSharp.Tests.Shared.Extensions; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class RootElementTests { [Fact] diff --git a/test/RestSharp.IntegrationTests/StatusCodeTests.cs b/test/RestSharp.Tests.Integrated/StatusCodeTests.cs similarity index 99% rename from test/RestSharp.IntegrationTests/StatusCodeTests.cs rename to test/RestSharp.Tests.Integrated/StatusCodeTests.cs index f63a3c296..746582af0 100644 --- a/test/RestSharp.IntegrationTests/StatusCodeTests.cs +++ b/test/RestSharp.Tests.Integrated/StatusCodeTests.cs @@ -4,7 +4,7 @@ using RestSharp.Tests.Shared.Extensions; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class StatusCodeTests : IDisposable { public StatusCodeTests() { diff --git a/test/RestSharp.IntegrationTests/StructuredSyntaxSuffixTests.cs b/test/RestSharp.Tests.Integrated/StructuredSyntaxSuffixTests.cs similarity index 98% rename from test/RestSharp.IntegrationTests/StructuredSyntaxSuffixTests.cs rename to test/RestSharp.Tests.Integrated/StructuredSyntaxSuffixTests.cs index 6a0be495b..3e2d93279 100644 --- a/test/RestSharp.IntegrationTests/StructuredSyntaxSuffixTests.cs +++ b/test/RestSharp.Tests.Integrated/StructuredSyntaxSuffixTests.cs @@ -3,7 +3,7 @@ using RestSharp.Tests.Shared.Extensions; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; public class StructuredSyntaxSuffixTests : IDisposable { readonly TestHttpServer _server; diff --git a/test/RestSharp.IntegrationTests/UploadFileTests.cs b/test/RestSharp.Tests.Integrated/UploadFileTests.cs similarity index 95% rename from test/RestSharp.IntegrationTests/UploadFileTests.cs rename to test/RestSharp.Tests.Integrated/UploadFileTests.cs index 616a8aacf..9ebc2f521 100644 --- a/test/RestSharp.IntegrationTests/UploadFileTests.cs +++ b/test/RestSharp.Tests.Integrated/UploadFileTests.cs @@ -1,6 +1,6 @@ -using RestSharp.IntegrationTests.Fixtures; +using RestSharp.Tests.Integrated.Fixtures; -namespace RestSharp.IntegrationTests; +namespace RestSharp.Tests.Integrated; [Collection(nameof(TestServerCollection))] public class UploadFileTests { diff --git a/test/RestSharp.IntegrationTests/xunit.runner.json b/test/RestSharp.Tests.Integrated/xunit.runner.json similarity index 100% rename from test/RestSharp.IntegrationTests/xunit.runner.json rename to test/RestSharp.Tests.Integrated/xunit.runner.json diff --git a/test/RestSharp.Serializers.Json.Tests/NewtonsoftJsonTests.cs b/test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs similarity index 98% rename from test/RestSharp.Serializers.Json.Tests/NewtonsoftJsonTests.cs rename to test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs index abfcb6c2a..11b370824 100644 --- a/test/RestSharp.Serializers.Json.Tests/NewtonsoftJsonTests.cs +++ b/test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs @@ -6,7 +6,7 @@ using RestSharp.Tests.Shared.Extensions; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.Serializers.Json.Tests; +namespace RestSharp.Tests.Serializers.Json; public class NewtonsoftJsonTests { static readonly Fixture Fixture = new(); diff --git a/test/RestSharp.Serializers.Json.Tests/RestSharp.Serializers.Json.Tests.csproj b/test/RestSharp.Tests.Serializers.Json/RestSharp.Tests.Serializers.Json.csproj similarity index 100% rename from test/RestSharp.Serializers.Json.Tests/RestSharp.Serializers.Json.Tests.csproj rename to test/RestSharp.Tests.Serializers.Json/RestSharp.Tests.Serializers.Json.csproj diff --git a/test/RestSharp.Serializers.Json.Tests/SampleData.cs b/test/RestSharp.Tests.Serializers.Json/SampleData.cs similarity index 87% rename from test/RestSharp.Serializers.Json.Tests/SampleData.cs rename to test/RestSharp.Tests.Serializers.Json/SampleData.cs index 4879253f2..c1170c507 100644 --- a/test/RestSharp.Serializers.Json.Tests/SampleData.cs +++ b/test/RestSharp.Tests.Serializers.Json/SampleData.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Json.Tests; +namespace RestSharp.Tests.Serializers.Json; public class TestClass { public string SimpleString { get; set; } diff --git a/test/RestSharp.Serializers.Json.Tests/SystemTextJsonTests.cs b/test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs similarity index 97% rename from test/RestSharp.Serializers.Json.Tests/SystemTextJsonTests.cs rename to test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs index b269d7fe3..f100a1b73 100644 --- a/test/RestSharp.Serializers.Json.Tests/SystemTextJsonTests.cs +++ b/test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs @@ -4,7 +4,7 @@ using RestSharp.Tests.Shared.Extensions; using RestSharp.Tests.Shared.Fixtures; -namespace RestSharp.Serializers.Json.Tests; +namespace RestSharp.Tests.Serializers.Json; public class SystemTextJsonTests { static readonly Fixture Fixture = new(); diff --git a/test/RestSharp.Serializers.Xml.Tests/NamespacedXmlTests.cs b/test/RestSharp.Tests.Serializers.Xml/NamespacedXmlTests.cs similarity index 98% rename from test/RestSharp.Serializers.Xml.Tests/NamespacedXmlTests.cs rename to test/RestSharp.Tests.Serializers.Xml/NamespacedXmlTests.cs index 148fc9d93..692329fd5 100644 --- a/test/RestSharp.Serializers.Xml.Tests/NamespacedXmlTests.cs +++ b/test/RestSharp.Tests.Serializers.Xml/NamespacedXmlTests.cs @@ -1,8 +1,9 @@ using System.Xml.Linq; -using RestSharp.Serializers.Xml.Tests.SampleClasses; -using RestSharp.Serializers.Xml.Tests.SampleClasses.DeserializeAsTest; +using RestSharp.Serializers.Xml; +using RestSharp.Tests.Serializers.Xml.SampleClasses; +using RestSharp.Tests.Serializers.Xml.SampleClasses.DeserializeAsTest; -namespace RestSharp.Serializers.Xml.Tests; +namespace RestSharp.Tests.Serializers.Xml; public class NamespacedXmlTests { const string GuidString = "AC1FC4BC-087A-4242-B8EE-C53EBE9887A5"; diff --git a/test/RestSharp.Serializers.Xml.Tests/RestSharp.Serializers.Xml.Tests.csproj b/test/RestSharp.Tests.Serializers.Xml/RestSharp.Tests.Serializers.Xml.csproj similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/RestSharp.Serializers.Xml.Tests.csproj rename to test/RestSharp.Tests.Serializers.Xml/RestSharp.Tests.Serializers.Xml.csproj diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/BearerToken.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/BearerToken.cs similarity index 80% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/BearerToken.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/BearerToken.cs index 0c858ec19..2e3faf202 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/BearerToken.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/BearerToken.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class BearerToken { public string AccessToken { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/BooleanTest.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/BooleanTest.cs similarity index 52% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/BooleanTest.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/BooleanTest.cs index 8e8bec8c8..cecd53dae 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/BooleanTest.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/BooleanTest.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class BooleanTest { public bool Value { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/ColorWithValue.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/ColorWithValue.cs similarity index 59% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/ColorWithValue.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/ColorWithValue.cs index c7411c903..5e873fe20 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/ColorWithValue.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/ColorWithValue.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; [DeserializeAs(Name = "Color")] public class ColorWithValue { diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/DeserializeAsTest/misc.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/DeserializeAsTest/misc.cs similarity index 70% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/DeserializeAsTest/misc.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/DeserializeAsTest/misc.cs index 60cbaa244..b8a4b9dfd 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/DeserializeAsTest/misc.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/DeserializeAsTest/misc.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses.DeserializeAsTest; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses.DeserializeAsTest; public class NodeWithAttributeAndValue { [DeserializeAs(Name = "attribute-value", Attribute = true)] diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/EmployeeTracker.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/EmployeeTracker.cs similarity index 92% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/EmployeeTracker.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/EmployeeTracker.cs index ae33edc94..a9dcb002e 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/EmployeeTracker.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/EmployeeTracker.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class EmployeeTracker { /// diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/EnumTest.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/EnumTest.cs similarity index 94% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/EnumTest.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/EnumTest.cs index 12439e94c..37efb663b 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/EnumTest.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/EnumTest.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public enum ByteEnum : byte { EnumMin = 0, EnumMax = 255 } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Goodreads.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Goodreads.cs similarity index 86% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/Goodreads.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/Goodreads.cs index 1f06ffcc2..5a8785b2f 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Goodreads.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Goodreads.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class GoodReadsReviewCollection { public int Start { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/GoogleWeatherWithAttributes.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/GoogleWeatherWithAttributes.cs similarity index 94% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/GoogleWeatherWithAttributes.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/GoogleWeatherWithAttributes.cs index 2b702cbdd..8117871bc 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/GoogleWeatherWithAttributes.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/GoogleWeatherWithAttributes.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class GoogleWeatherApi { public string Version { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/HeaderAndRows.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/HeaderAndRows.cs similarity index 77% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/HeaderAndRows.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/HeaderAndRows.cs index 1d3339f49..d0a7369f8 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/HeaderAndRows.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/HeaderAndRows.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class Header { public string Title { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/JsonLists.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/JsonLists.cs similarity index 65% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/JsonLists.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/JsonLists.cs index d1e016882..f94fb130c 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/JsonLists.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/JsonLists.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class JsonLists { public List Names { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Lastfm.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Lastfm.cs similarity index 93% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/Lastfm.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/Lastfm.cs index 75fb02730..6a5002234 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Lastfm.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Lastfm.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class Event : LastfmBase { public string id { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/ListSamples.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/ListSamples.cs similarity index 92% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/ListSamples.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/ListSamples.cs index c214b7008..5cb169682 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/ListSamples.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/ListSamples.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class SimpleTypesListSample { public List Names { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Oddball.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Oddball.cs similarity index 79% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/Oddball.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/Oddball.cs index 3eef8c02a..53eedf2e9 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Oddball.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Oddball.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; [DeserializeAs(Name = "oddballRootName")] public class Oddball { diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/SOUser.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/SOUser.cs similarity index 89% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/SOUser.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/SOUser.cs index 90901f617..807452dae 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/SOUser.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/SOUser.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class SoUser { public int Id { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Struct.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Struct.cs similarity index 69% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/Struct.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/Struct.cs index 3965c5a5d..7a64ab5b7 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/Struct.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/Struct.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public struct SimpleStruct { public string One { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/TwilioCallList.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/TwilioCallList.cs similarity index 74% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/TwilioCallList.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/TwilioCallList.cs index f3e3c3d1b..127a30836 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/TwilioCallList.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/TwilioCallList.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class TwilioCallList : List { public int Page { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/eventful.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/eventful.cs similarity index 97% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/eventful.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/eventful.cs index 820d514bf..57ab73c52 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/eventful.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/eventful.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class VenueSearch { public string total_items { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/foursq.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/foursq.cs similarity index 69% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/foursq.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/foursq.cs index a362c0634..82e8d7439 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/foursq.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/foursq.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class VenuesResponse { public List Groups { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/googleweather.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/googleweather.cs similarity index 95% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/googleweather.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/googleweather.cs index 25c8508ea..2e6d711cc 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/googleweather.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/googleweather.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class xml_api_reply { public string version { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/misc.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/misc.cs similarity index 98% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/misc.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/misc.cs index 3ab733479..9f88370e6 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/misc.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/misc.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class PersonForXml { public string Name { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/nullables.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/nullables.cs similarity index 71% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/nullables.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/nullables.cs index 0b2b1ed14..5cfe46a80 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/nullables.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/nullables.cs @@ -1,4 +1,4 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class NullableValues { public int? Id { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/twitter.cs b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/twitter.cs similarity index 96% rename from test/RestSharp.Serializers.Xml.Tests/SampleClasses/twitter.cs rename to test/RestSharp.Tests.Serializers.Xml/SampleClasses/twitter.cs index 75d6c6051..53cdb83b1 100644 --- a/test/RestSharp.Serializers.Xml.Tests/SampleClasses/twitter.cs +++ b/test/RestSharp.Tests.Serializers.Xml/SampleClasses/twitter.cs @@ -1,4 +1,6 @@ -namespace RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; + +namespace RestSharp.Tests.Serializers.Xml.SampleClasses; public class status { public bool truncated { get; set; } diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/Goodreads.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/Goodreads.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/Goodreads.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/Goodreads.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/GoodreadsFormatError.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/GoodreadsFormatError.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/GoodreadsFormatError.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/GoodreadsFormatError.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/GoogleWeather.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/GoogleWeather.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/GoogleWeather.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/GoogleWeather.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/InlineListSample.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/InlineListSample.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/InlineListSample.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/InlineListSample.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/Lastfm.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/Lastfm.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/Lastfm.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/Lastfm.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/ListWithAttributes.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/ListWithAttributes.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/ListWithAttributes.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/ListWithAttributes.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/NestedListSample.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/NestedListSample.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/NestedListSample.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/NestedListSample.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/boolean_from_number.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/boolean_from_number.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/boolean_from_number.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/boolean_from_number.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/boolean_from_string.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/boolean_from_string.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/boolean_from_string.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/boolean_from_string.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/deserialize_as_list.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/deserialize_as_list.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/deserialize_as_list.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/deserialize_as_list.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/directlists.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/directlists.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/directlists.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/directlists.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/eventful.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/eventful.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/eventful.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/eventful.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/header_and_rows.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/header_and_rows.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/header_and_rows.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/header_and_rows.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/restsharp.nuspec b/test/RestSharp.Tests.Serializers.Xml/SampleData/restsharp.nuspec similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/restsharp.nuspec rename to test/RestSharp.Tests.Serializers.Xml/SampleData/restsharp.nuspec diff --git a/test/RestSharp.Serializers.Xml.Tests/SampleData/xmllists.xml b/test/RestSharp.Tests.Serializers.Xml/SampleData/xmllists.xml similarity index 100% rename from test/RestSharp.Serializers.Xml.Tests/SampleData/xmllists.xml rename to test/RestSharp.Tests.Serializers.Xml/SampleData/xmllists.xml diff --git a/test/RestSharp.Serializers.Xml.Tests/XmlAttributeDeserializerTests.cs b/test/RestSharp.Tests.Serializers.Xml/XmlAttributeDeserializerTests.cs similarity index 99% rename from test/RestSharp.Serializers.Xml.Tests/XmlAttributeDeserializerTests.cs rename to test/RestSharp.Tests.Serializers.Xml/XmlAttributeDeserializerTests.cs index 99ae2a7ab..54a34b9b4 100644 --- a/test/RestSharp.Serializers.Xml.Tests/XmlAttributeDeserializerTests.cs +++ b/test/RestSharp.Tests.Serializers.Xml/XmlAttributeDeserializerTests.cs @@ -1,8 +1,9 @@ using System.Globalization; using System.Xml.Linq; -using RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers.Xml; +using RestSharp.Tests.Serializers.Xml.SampleClasses; -namespace RestSharp.Serializers.Xml.Tests; +namespace RestSharp.Tests.Serializers.Xml; public class XmlAttributeDeserializerTests { const string GuidString = "AC1FC4BC-087A-4242-B8EE-C53EBE9887A5"; diff --git a/test/RestSharp.Serializers.Xml.Tests/XmlDeserializerTests.cs b/test/RestSharp.Tests.Serializers.Xml/XmlDeserializerTests.cs similarity index 99% rename from test/RestSharp.Serializers.Xml.Tests/XmlDeserializerTests.cs rename to test/RestSharp.Tests.Serializers.Xml/XmlDeserializerTests.cs index adb2cb32c..f429085cf 100644 --- a/test/RestSharp.Serializers.Xml.Tests/XmlDeserializerTests.cs +++ b/test/RestSharp.Tests.Serializers.Xml/XmlDeserializerTests.cs @@ -1,9 +1,10 @@ using System.Globalization; using System.Xml.Linq; -using RestSharp.Serializers.Xml.Tests.SampleClasses; -using RestSharp.Serializers.Xml.Tests.SampleClasses.DeserializeAsTest; +using RestSharp.Serializers.Xml; +using RestSharp.Tests.Serializers.Xml.SampleClasses; +using RestSharp.Tests.Serializers.Xml.SampleClasses.DeserializeAsTest; -namespace RestSharp.Serializers.Xml.Tests; +namespace RestSharp.Tests.Serializers.Xml; public class XmlDeserializerTests { const string GuidString = "AC1FC4BC-087A-4242-B8EE-C53EBE9887A5"; diff --git a/test/RestSharp.Serializers.Xml.Tests/XmlSerializerTests.cs b/test/RestSharp.Tests.Serializers.Xml/XmlSerializerTests.cs similarity index 99% rename from test/RestSharp.Serializers.Xml.Tests/XmlSerializerTests.cs rename to test/RestSharp.Tests.Serializers.Xml/XmlSerializerTests.cs index 40e4c61e4..e88e0e73c 100644 --- a/test/RestSharp.Serializers.Xml.Tests/XmlSerializerTests.cs +++ b/test/RestSharp.Tests.Serializers.Xml/XmlSerializerTests.cs @@ -1,8 +1,10 @@ using System.Globalization; using System.Xml.Linq; -using RestSharp.Serializers.Xml.Tests.SampleClasses; +using RestSharp.Serializers; +using RestSharp.Serializers.Xml; +using RestSharp.Tests.Serializers.Xml.SampleClasses; -namespace RestSharp.Serializers.Xml.Tests; +namespace RestSharp.Tests.Serializers.Xml; public class XmlSerializerTests { public XmlSerializerTests() { From c94dfcdf9936e78391779efc143f276b9a1065ad Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Wed, 19 Jan 2022 21:43:14 +0100 Subject: [PATCH 4/5] Finalize the change in serializer detection --- src/RestSharp/RestClient.Serialization.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/RestSharp/RestClient.Serialization.cs b/src/RestSharp/RestClient.Serialization.cs index f94dbbde8..3bcc4c056 100644 --- a/src/RestSharp/RestClient.Serialization.cs +++ b/src/RestSharp/RestClient.Serialization.cs @@ -92,13 +92,15 @@ internal RestResponse Deserialize(RestRequest request, RestResponse raw) { } IDeserializer? GetContentDeserializer(RestResponseBase response, DataFormat requestFormat) { - if (response.ContentType == null) return null; + var contentType = response.ContentType ?? DetectContentType(); + if (contentType == null) return null; - var serializer = Serializers.Values.FirstOrDefault(x => x.SupportsContentType(response.ContentType)); + var serializer = Serializers.Values.FirstOrDefault(x => x.SupportsContentType(contentType)); var factory = serializer ?? (Serializers.ContainsKey(requestFormat) ? Serializers[requestFormat] : null); return factory?.GetSerializer().Deserializer; string? DetectContentType() - => response.Content!.StartsWith("<") ? ContentType.Xml : response.Content.StartsWith("{") || response.Content.StartsWith("[") ? ContentType.Json : null; + => response.Content!.StartsWith("<") ? ContentType.Xml + : response.Content.StartsWith("{") || response.Content.StartsWith("[") ? ContentType.Json : null; } } \ No newline at end of file From 5955ce46426869073c81299106ecef6e3bd9b721 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Thu, 20 Jan 2022 10:44:48 +0100 Subject: [PATCH 5/5] Add ignore case for serializer detection --- .../Serializers/Json/SystemTextJsonSerializer.cs | 13 +++++-------- src/RestSharp/Serializers/Xml/XmlRestSerializer.cs | 9 ++++----- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs b/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs index 142d3bf8c..358072e55 100644 --- a/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs +++ b/src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs @@ -36,14 +36,11 @@ public class SystemTextJsonSerializer : IRestSerializer, ISerializer, IDeseriali public T? Deserialize(RestResponse response) => JsonSerializer.Deserialize(response.Content!, _options); - public ISerializer Serializer => this; - public IDeserializer Deserializer => this; - - public string[] AcceptedContentTypes => Serializers.ContentType.JsonAccept; - public string ContentType { get; set; } = "application/json"; - public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("json"); - - public DataFormat DataFormat => DataFormat.Json; + public ISerializer Serializer => this; + public IDeserializer Deserializer => this; + public DataFormat DataFormat => DataFormat.Json; + public string[] AcceptedContentTypes => Serializers.ContentType.JsonAccept; + public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("json", StringComparison.InvariantCultureIgnoreCase); } \ No newline at end of file diff --git a/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs b/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs index 31a9b84e6..37c54a46c 100644 --- a/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs +++ b/src/RestSharp/Serializers/Xml/XmlRestSerializer.cs @@ -25,11 +25,10 @@ public XmlRestSerializer(IXmlSerializer xmlSerializer, IXmlDeserializer xmlDeser _xmlSerializer = xmlSerializer; } - public ISerializer Serializer => _xmlSerializer; - public IDeserializer Deserializer => _xmlDeserializer; - public string[] AcceptedContentTypes => ContentType.XmlAccept; - - public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("xml"); + public ISerializer Serializer => _xmlSerializer; + public IDeserializer Deserializer => _xmlDeserializer; + public string[] AcceptedContentTypes => ContentType.XmlAccept; + public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("xml", StringComparison.InvariantCultureIgnoreCase); public DataFormat DataFormat => DataFormat.Xml;