Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions Retailcrm/Connection.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Retailcrm
{
Expand All @@ -17,36 +18,32 @@ public class Connection
public Connection(string url, string key)
{
if ("/" != url.Substring(url.Length - 1, 1))
{
url += "/";
}

url += "api/";

_request = new Request(url, new Dictionary<string, object> { { "apiKey", key } });
}

/// <summary>
/// Get available API versions
/// </summary>
/// <returns></returns>
public Response Versions()
public Task<Response> Versions()
{
return _request.MakeRequest(
"api-versions",
Request.MethodGet
System.Net.Http.HttpMethod.Get
);
}

/// <summary>
/// Get available API methods
/// </summary>
/// <returns></returns>
public Response Credentials()
public Task<Response> Credentials()
{
return _request.MakeRequest(
"credentials",
Request.MethodGet
System.Net.Http.HttpMethod.Get
);
}
}
Expand Down
18 changes: 18 additions & 0 deletions Retailcrm/Http2RequestHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Retailcrm
{
public class Http2CustomHandler : WinHttpHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Version = new Version("2.0");
return base.SendAsync(request, cancellationToken);
}
}
}
88 changes: 27 additions & 61 deletions Retailcrm/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Retailcrm
{
Expand All @@ -12,19 +14,16 @@ namespace Retailcrm
/// </summary>
public class Request
{
/// <summary>
/// Get method
/// </summary>
public const string MethodGet = "GET";
/// <summary>
/// Post method
/// </summary>
public const string MethodPost = "POST";
private const string UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
private const string ContentType = "application/x-www-form-urlencoded";

private readonly string _url;
private readonly Dictionary<string, object> _defaultParameters;
private static readonly HttpClient DefaultClient = new(new Http2CustomHandler
{
EnableMultipleHttp2Connections = true,
});
private readonly HttpClient _httpClient;

/// <summary>
/// Request constructor
Expand All @@ -33,12 +32,18 @@ public class Request
/// <param name="parameters"></param>
/// <exception cref="ArgumentException"></exception>
public Request(string apiUrl, Dictionary<string, object> parameters = null)
: this(DefaultClient, apiUrl, parameters)
{

}

public Request(HttpClient client, string apiUrl, Dictionary<string, object> parameters = null)
{
if (apiUrl.IndexOf("https://", StringComparison.Ordinal) == -1)
{
throw new ArgumentException("API schema requires HTTPS protocol");
}

_httpClient = client;
_url = apiUrl;
_defaultParameters = parameters;
}
Expand All @@ -52,69 +57,30 @@ public Request(string apiUrl, Dictionary<string, object> parameters = null)
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="WebException"></exception>
public Response MakeRequest(string path, string method, Dictionary<string, object> parameters = null)
public async Task<Response> MakeRequest(string path, HttpMethod method, Dictionary<string, object> parameters = null)
{
string[] allowedMethods = { MethodGet, MethodPost };

if (allowedMethods.Contains(method) == false)
{
throw new ArgumentException($"Method {method} is not valid. Allowed HTTP methods are {string.Join(", ", allowedMethods)}");
}

if (parameters == null)
{
parameters = new Dictionary<string, object>();
}
if (method != HttpMethod.Get && method != HttpMethod.Post)
throw new ArgumentException($"Method {method} is not valid. Allowed HTTP methods are GET and POST");
parameters ??= [];

parameters = _defaultParameters.Union(parameters).ToDictionary(k => k.Key, v => v.Value);
path = _url + path;

string httpQuery = QueryBuilder.BuildQueryString(parameters);

if (method.Equals(MethodGet) && parameters.Count > 0)
{
if (method == HttpMethod.Get && parameters.Count > 0)
path += "?" + httpQuery;
}

Exception exception = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(path);
request.Method = method;

if (method.Equals(MethodPost))
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(httpQuery);
request.ContentLength = bytes.Length;
request.ContentType = ContentType;
request.UserAgent = UserAgent;

Stream post = request.GetRequestStream();
post.Write(bytes, 0, bytes.Length);
post.Flush();
post.Close();
}

HttpWebResponse response;

try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException webException)
using var httpRequest = new HttpRequestMessage(method, path);
using var content = new StringContent(httpQuery);
if (method == HttpMethod.Post)
{
response = (HttpWebResponse)webException.Response;
exception = webException;
httpRequest.Content = content;
httpRequest.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(ContentType);
httpRequest.Headers.UserAgent.ParseAdd(UserAgent);
}

if (request == null || response == null)
{
throw new WebException(exception.ToString(), exception);
}

StreamReader reader = new StreamReader(response.GetResponseStream());
using var response = await _httpClient.SendAsync(httpRequest);
using StreamReader reader = new(await response.Content.ReadAsStreamAsync());
string responseBody = reader.ReadToEnd();
int statusCode = (int)response.StatusCode;

return new Response(statusCode, responseBody);
}
}
Expand Down
23 changes: 22 additions & 1 deletion Retailcrm/Retailcrm.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Retailcrm</RootNamespace>
<AssemblyName>Retailcrm</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -32,7 +34,24 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WinHttpHandler, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.WinHttpHandler.9.0.0\lib\net462\System.Net.Http.WinHttpHandler.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
Expand All @@ -41,6 +60,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Connection.cs" />
<Compile Include="Http2RequestHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="QueryBuilder.cs" />
<Compile Include="Request.cs" />
Expand Down Expand Up @@ -78,6 +98,7 @@
<Compile Include="Versions\V5\Users.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Retailcrm.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down
33 changes: 18 additions & 15 deletions Retailcrm/Retailcrm.nuspec
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Retailcrm.SDK</id>
<version>5.1.3</version>
<title>$title$</title>
<authors>RetailCRM</authors>
<owners>RetailCRM</owners>
<license type="expression">MIT</license>
<projectUrl>https://github.com/retailcrmapi-client-dotnet</projectUrl>
<iconUrl>https://s3-s1.retailcrm.tech/eu-central-1/retailcrm-static/branding/retailcrm/favicon/favicon.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Multiversion API client for RetailCRM</description>
<releaseNotes>Rebranding</releaseNotes>
<copyright>Copyright 2017-2020</copyright>
<tags>crm ecommerce retailcrm sdk</tags>
</metadata>
<metadata>
<id>Retailcrm.SDK</id>
<version>5.2.0</version>
<title>$title$</title>
<authors>RetailCRM</authors>
<owners>RetailCRM</owners>
<license type="expression">MIT</license>
<projectUrl>https://github.com/retailcrmapi-client-dotnet</projectUrl>
<iconUrl>https://s3-s1.retailcrm.tech/eu-central-1/retailcrm-static/branding/retailcrm/favicon/favicon.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Multiversion API client for RetailCRM</description>
<releaseNotes>Move to async and Http 2.0</releaseNotes>
<copyright>Copyright 2017-2024</copyright>
<tags>crm ecommerce retailcrm sdk</tags>
<dependencies>
<dependency id="System.Net.Http.WinHttpHandler" version="9.0.0" />
</dependencies>
</metadata>
</package>
Loading