Skip to content

Commit cd69557

Browse files
authored
Merge pull request #87 from tranpl/dev/mike
Add CustomFormUrlEncodedContent
2 parents 11d953e + 25f0d43 commit cd69557

File tree

7 files changed

+295
-157
lines changed

7 files changed

+295
-157
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ __Install directly in Package Manager Console or Command Line Interface__
7373
```C#
7474
Package Manager
7575

76-
Install-Package RedcapAPI -Version 1.0.7
76+
Install-Package RedcapAPI -Version 1.0.8
7777

7878
```
7979

8080
```C#
8181
.NET CLI
8282

83-
dotnet add package RedcapAPI --version 1.0.7
83+
dotnet add package RedcapAPI --version 1.0.8
8484

8585
```
8686

8787
```C#
8888
Paket CLI
8989

90-
paket add RedcapAPI --version 1.0.7
90+
paket add RedcapAPI --version 1.0.8
9191

9292
```
9393

RedcapApi/Api/Redcap.cs

+37-21
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net.Http;
4+
using System.Net.Http.Headers;
5+
using System.Text;
6+
7+
namespace Redcap.Http
8+
{
9+
/// <summary>
10+
/// https://stackoverflow.com/a/23740338
11+
/// </summary>
12+
public class CustomFormUrlEncodedContent : ByteArrayContent
13+
{
14+
/// <summary>
15+
///
16+
/// </summary>
17+
/// <param name="nameValueCollection"></param>
18+
public CustomFormUrlEncodedContent(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
19+
: base(CustomFormUrlEncodedContent.GetContentByteArray(nameValueCollection))
20+
{
21+
base.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
22+
}
23+
private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
24+
{
25+
if (nameValueCollection == null)
26+
{
27+
throw new ArgumentNullException("nameValueCollection");
28+
}
29+
StringBuilder stringBuilder = new StringBuilder();
30+
foreach (KeyValuePair<string, string> current in nameValueCollection)
31+
{
32+
if (stringBuilder.Length > 0)
33+
{
34+
stringBuilder.Append('&');
35+
}
36+
37+
stringBuilder.Append(CustomFormUrlEncodedContent.Encode(current.Key));
38+
stringBuilder.Append('=');
39+
stringBuilder.Append(CustomFormUrlEncodedContent.Encode(current.Value));
40+
}
41+
return Encoding.Default.GetBytes(stringBuilder.ToString());
42+
}
43+
private static string Encode(string data)
44+
{
45+
if (string.IsNullOrEmpty(data))
46+
{
47+
return string.Empty;
48+
}
49+
return System.Net.WebUtility.UrlEncode(data).Replace("%20", "+");
50+
}
51+
}
52+
}

RedcapApi/Redcap.csproj

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
<Description>This library allows applications on the .NET platform to make http calls to REDCap instances.</Description>
1111
<Product>Redcap Api Library</Product>
1212
<PackageId>RedcapAPI</PackageId>
13-
<Version>1.0.7</Version>
14-
<AssemblyVersion>1.0.7.0</AssemblyVersion>
13+
<Version>1.0.8</Version>
14+
<AssemblyVersion>1.0.8.0</AssemblyVersion>
1515
<PackageTags>redcap api library</PackageTags>
1616
<PackageReleaseNotes>Additional tests for latest release.
1717
Additional methods include: ImportRepeatingInstrumentsAndEvents
@@ -22,9 +22,10 @@ Bug fixes</PackageReleaseNotes>
2222
<OutputType>Library</OutputType>
2323
<StartupObject />
2424
<NeutralLanguage>en</NeutralLanguage>
25-
<FileVersion>1.0.7.0</FileVersion>
25+
<FileVersion>1.0.8.0</FileVersion>
2626
<PackageLicenseUrl>https://github.com/cctrbic/redcap-api/blob/master/LICENSE.md</PackageLicenseUrl>
2727
<Copyright>https://github.com/cctrbic/redcap-api/blob/master/LICENSE.md</Copyright>
28+
<PackageIconUrl>https://vortex.cctr.vcu.edu/images/ram_crest_160.png</PackageIconUrl>
2829
</PropertyGroup>
2930
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
3031
<Optimize>false</Optimize>

RedcapApi/Utilities/Utils.cs

+38-98
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Newtonsoft.Json;
2+
using Redcap.Http;
23
using Redcap.Models;
34
using Serilog;
45
using System;
@@ -213,10 +214,10 @@ public static async Task<string> ConvertIntArraytoString(this RedcapApi redcapAp
213214
try
214215
{
215216
StringBuilder builder = new StringBuilder();
216-
foreach (var v in inputArray)
217+
foreach (var intValue in inputArray)
217218
{
218219

219-
builder.Append(v);
220+
builder.Append(intValue);
220221
// We do not need to append the , if less than or equal to a single string
221222
if (inputArray.Length <= 1)
222223
{
@@ -614,7 +615,7 @@ public static async Task<Stream> GetStreamContentAsync(this RedcapApi redcapApi,
614615
/// <param name="payload">data</param>
615616
/// <param name="uri">URI of the api instance</param>
616617
/// <returns>string</returns>
617-
public static async Task<string> SendRequestAsync(this RedcapApi redcapApi, MultipartFormDataContent payload, Uri uri)
618+
public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi, MultipartFormDataContent payload, Uri uri)
618619
{
619620
try
620621
{
@@ -644,9 +645,8 @@ public static async Task<string> SendRequestAsync(this RedcapApi redcapApi, Mult
644645
/// <param name="redcapApi"></param>
645646
/// <param name="payload">data</param>
646647
/// <param name="uri">URI of the api instance</param>
647-
/// <param name="isLargeDataset">Requests size > 32k chars </param>
648648
/// <returns></returns>
649-
public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi, Dictionary<string, string> payload, Uri uri, bool isLargeDataset = false)
649+
public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi, Dictionary<string, string> payload, Uri uri)
650650
{
651651
try
652652
{
@@ -666,112 +666,53 @@ public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi,
666666
payload.Remove(pathkey);
667667
}
668668

669-
/*
670-
* Encode the values for payload
671-
* Add in ability to process large data set, using StringContent
672-
* Thanks to Ibrahim for pointing this out.
673-
* https://stackoverflow.com/questions/23703735/how-to-set-large-string-inside-httpcontent-when-using-httpclient/23740338
674-
*/
675-
if (isLargeDataset)
669+
using (var content = new CustomFormUrlEncodedContent(payload))
676670
{
677-
/*
678-
* Send request with large data set
679-
*/
680-
681-
var serializedPayload = JsonConvert.SerializeObject(payload);
682-
using (var content = new StringContent(serializedPayload, Encoding.UTF8, "application/json"))
671+
using (var response = await client.PostAsync(uri, content))
683672
{
684-
using (var response = await client.PostAsync(uri, content))
673+
if (response.IsSuccessStatusCode)
685674
{
686-
if (response.IsSuccessStatusCode)
675+
// Get the filename so we can save with the name
676+
var headers = response.Content.Headers;
677+
var fileName = headers.ContentType.Parameters.Select(x => x.Value).FirstOrDefault();
678+
if (!string.IsNullOrEmpty(fileName))
687679
{
688-
// Get the filename so we can save with the name
689-
var headers = response.Content.Headers;
690-
var fileName = headers.ContentType.Parameters.Select(x => x.Value).FirstOrDefault();
691-
if (!string.IsNullOrEmpty(fileName))
692-
{
693-
var contentDisposition = response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
694-
{
695-
FileName = fileName
696-
};
697-
}
698-
699-
if (!string.IsNullOrEmpty(pathValue))
700-
{
701-
// save the file to a specified location using an extension method
702-
await response.Content.ReadAsFileAsync(fileName, pathValue, true);
703-
_responseMessage = fileName;
704-
}
705-
else
680+
var contentDisposition = response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
706681
{
707-
_responseMessage = await response.Content.ReadAsStringAsync();
708-
}
709-
682+
FileName = fileName
683+
};
710684
}
711-
else
712-
{
713-
_responseMessage = await response.Content.ReadAsStringAsync();
714-
}
715-
}
716685

717-
}
718-
return _responseMessage;
719-
}
720-
else
721-
{
722-
/*
723-
* Maximum character limit of 32,000 using FormUrlEncodedContent
724-
* Send request using small data set
725-
*/
726-
using (var content = new FormUrlEncodedContent(payload))
727-
{
728-
using (var response = await client.PostAsync(uri, content))
729-
{
730-
if (response.IsSuccessStatusCode)
686+
687+
if (!string.IsNullOrEmpty(pathValue))
731688
{
732-
// Get the filename so we can save with the name
733-
var headers = response.Content.Headers;
734-
var fileName = headers.ContentType.Parameters.Select(x => x.Value).FirstOrDefault();
735-
if (!string.IsNullOrEmpty(fileName))
689+
var fileExtension = payload.Where(x => x.Key == "content" && x.Value == "pdf").SingleOrDefault().Value;
690+
if (!string.IsNullOrEmpty(fileExtension))
736691
{
737-
var contentDisposition = response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
738-
{
739-
FileName = fileName
740-
};
741-
}
742-
692+
// pdf
693+
fileName = payload.Where(x => x.Key == "instrument").SingleOrDefault().Value;
694+
// to do , make extensions for various types
695+
// save the file to a specified location using an extension method
696+
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);
743697

744-
if (!string.IsNullOrEmpty(pathValue))
745-
{
746-
var fileExtension = payload.Where(x => x.Key == "content" && x.Value == "pdf").SingleOrDefault().Value;
747-
if (!string.IsNullOrEmpty(fileExtension))
748-
{
749-
// pdf
750-
fileName = payload.Where(x => x.Key == "instrument").SingleOrDefault().Value;
751-
// to do , make extensions for various types
752-
// save the file to a specified location using an extension method
753-
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);
754-
755-
}
756-
else
757-
{
758-
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);
759-
760-
}
761-
_responseMessage = fileName;
762698
}
763699
else
764700
{
765-
_responseMessage = await response.Content.ReadAsStringAsync();
701+
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);
702+
766703
}
704+
_responseMessage = fileName;
767705
}
768706
else
769707
{
770708
_responseMessage = await response.Content.ReadAsStringAsync();
771709
}
772710
}
711+
else
712+
{
713+
_responseMessage = await response.Content.ReadAsStringAsync();
714+
}
773715
}
774-
775716
}
776717
return _responseMessage;
777718
}
@@ -781,14 +722,13 @@ public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi,
781722
Log.Error($"{Ex.Message}");
782723
return Empty;
783724
}
784-
}
785-
/// <summary>
786-
/// Sends http request to api
787-
/// </summary>
788-
/// <param name="redcapApi"></param>
789-
/// <param name="payload">data </param>
790-
/// <param name="uri">URI of the api instance</param>
791-
/// <returns>string</returns>
725+
} /// <summary>
726+
/// Sends http request to api
727+
/// </summary>
728+
/// <param name="redcapApi"></param>
729+
/// <param name="payload">data </param>
730+
/// <param name="uri">URI of the api instance</param>
731+
/// <returns>string</returns>
792732
public static async Task<string> SendPostRequest(this RedcapApi redcapApi, Dictionary<string, string> payload, Uri uri)
793733
{
794734
string responseString;

0 commit comments

Comments
 (0)