Skip to content

Commit

Permalink
Merge pull request #87 from tranpl/dev/mike
Browse files Browse the repository at this point in the history
Add CustomFormUrlEncodedContent
  • Loading branch information
cctrbic authored Jan 27, 2020
2 parents 11d953e + 25f0d43 commit cd69557
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 157 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,21 @@ __Install directly in Package Manager Console or Command Line Interface__
```C#
Package Manager

Install-Package RedcapAPI -Version 1.0.7
Install-Package RedcapAPI -Version 1.0.8

```

```C#
.NET CLI

dotnet add package RedcapAPI --version 1.0.7
dotnet add package RedcapAPI --version 1.0.8

```

```C#
Paket CLI

paket add RedcapAPI --version 1.0.7
paket add RedcapAPI --version 1.0.8

```

Expand Down
58 changes: 37 additions & 21 deletions RedcapApi/Api/Redcap.cs

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions RedcapApi/Http/CustomFormUrlEncodedContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace Redcap.Http
{
/// <summary>
/// https://stackoverflow.com/a/23740338
/// </summary>
public class CustomFormUrlEncodedContent : ByteArrayContent
{
/// <summary>
///
/// </summary>
/// <param name="nameValueCollection"></param>
public CustomFormUrlEncodedContent(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
: base(CustomFormUrlEncodedContent.GetContentByteArray(nameValueCollection))
{
base.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
}
private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
{
if (nameValueCollection == null)
{
throw new ArgumentNullException("nameValueCollection");
}
StringBuilder stringBuilder = new StringBuilder();
foreach (KeyValuePair<string, string> current in nameValueCollection)
{
if (stringBuilder.Length > 0)
{
stringBuilder.Append('&');
}

stringBuilder.Append(CustomFormUrlEncodedContent.Encode(current.Key));
stringBuilder.Append('=');
stringBuilder.Append(CustomFormUrlEncodedContent.Encode(current.Value));
}
return Encoding.Default.GetBytes(stringBuilder.ToString());
}
private static string Encode(string data)
{
if (string.IsNullOrEmpty(data))
{
return string.Empty;
}
return System.Net.WebUtility.UrlEncode(data).Replace("%20", "+");
}
}
}
7 changes: 4 additions & 3 deletions RedcapApi/Redcap.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<Description>This library allows applications on the .NET platform to make http calls to REDCap instances.</Description>
<Product>Redcap Api Library</Product>
<PackageId>RedcapAPI</PackageId>
<Version>1.0.7</Version>
<AssemblyVersion>1.0.7.0</AssemblyVersion>
<Version>1.0.8</Version>
<AssemblyVersion>1.0.8.0</AssemblyVersion>
<PackageTags>redcap api library</PackageTags>
<PackageReleaseNotes>Additional tests for latest release.
Additional methods include: ImportRepeatingInstrumentsAndEvents
Expand All @@ -22,9 +22,10 @@ Bug fixes</PackageReleaseNotes>
<OutputType>Library</OutputType>
<StartupObject />
<NeutralLanguage>en</NeutralLanguage>
<FileVersion>1.0.7.0</FileVersion>
<FileVersion>1.0.8.0</FileVersion>
<PackageLicenseUrl>https://github.com/cctrbic/redcap-api/blob/master/LICENSE.md</PackageLicenseUrl>
<Copyright>https://github.com/cctrbic/redcap-api/blob/master/LICENSE.md</Copyright>
<PackageIconUrl>https://vortex.cctr.vcu.edu/images/ram_crest_160.png</PackageIconUrl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>false</Optimize>
Expand Down
136 changes: 38 additions & 98 deletions RedcapApi/Utilities/Utils.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Redcap.Http;
using Redcap.Models;
using Serilog;
using System;
Expand Down Expand Up @@ -213,10 +214,10 @@ public static async Task<string> ConvertIntArraytoString(this RedcapApi redcapAp
try
{
StringBuilder builder = new StringBuilder();
foreach (var v in inputArray)
foreach (var intValue in inputArray)
{

builder.Append(v);
builder.Append(intValue);
// We do not need to append the , if less than or equal to a single string
if (inputArray.Length <= 1)
{
Expand Down Expand Up @@ -614,7 +615,7 @@ public static async Task<Stream> GetStreamContentAsync(this RedcapApi redcapApi,
/// <param name="payload">data</param>
/// <param name="uri">URI of the api instance</param>
/// <returns>string</returns>
public static async Task<string> SendRequestAsync(this RedcapApi redcapApi, MultipartFormDataContent payload, Uri uri)
public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi, MultipartFormDataContent payload, Uri uri)
{
try
{
Expand Down Expand Up @@ -644,9 +645,8 @@ public static async Task<string> SendRequestAsync(this RedcapApi redcapApi, Mult
/// <param name="redcapApi"></param>
/// <param name="payload">data</param>
/// <param name="uri">URI of the api instance</param>
/// <param name="isLargeDataset">Requests size > 32k chars </param>
/// <returns></returns>
public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi, Dictionary<string, string> payload, Uri uri, bool isLargeDataset = false)
public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi, Dictionary<string, string> payload, Uri uri)
{
try
{
Expand All @@ -666,112 +666,53 @@ public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi,
payload.Remove(pathkey);
}

/*
* Encode the values for payload
* Add in ability to process large data set, using StringContent
* Thanks to Ibrahim for pointing this out.
* https://stackoverflow.com/questions/23703735/how-to-set-large-string-inside-httpcontent-when-using-httpclient/23740338
*/
if (isLargeDataset)
using (var content = new CustomFormUrlEncodedContent(payload))
{
/*
* Send request with large data set
*/

var serializedPayload = JsonConvert.SerializeObject(payload);
using (var content = new StringContent(serializedPayload, Encoding.UTF8, "application/json"))
using (var response = await client.PostAsync(uri, content))
{
using (var response = await client.PostAsync(uri, content))
if (response.IsSuccessStatusCode)
{
if (response.IsSuccessStatusCode)
// Get the filename so we can save with the name
var headers = response.Content.Headers;
var fileName = headers.ContentType.Parameters.Select(x => x.Value).FirstOrDefault();
if (!string.IsNullOrEmpty(fileName))
{
// Get the filename so we can save with the name
var headers = response.Content.Headers;
var fileName = headers.ContentType.Parameters.Select(x => x.Value).FirstOrDefault();
if (!string.IsNullOrEmpty(fileName))
{
var contentDisposition = response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
};
}

if (!string.IsNullOrEmpty(pathValue))
{
// save the file to a specified location using an extension method
await response.Content.ReadAsFileAsync(fileName, pathValue, true);
_responseMessage = fileName;
}
else
var contentDisposition = response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
_responseMessage = await response.Content.ReadAsStringAsync();
}

FileName = fileName
};
}
else
{
_responseMessage = await response.Content.ReadAsStringAsync();
}
}

}
return _responseMessage;
}
else
{
/*
* Maximum character limit of 32,000 using FormUrlEncodedContent
* Send request using small data set
*/
using (var content = new FormUrlEncodedContent(payload))
{
using (var response = await client.PostAsync(uri, content))
{
if (response.IsSuccessStatusCode)

if (!string.IsNullOrEmpty(pathValue))
{
// Get the filename so we can save with the name
var headers = response.Content.Headers;
var fileName = headers.ContentType.Parameters.Select(x => x.Value).FirstOrDefault();
if (!string.IsNullOrEmpty(fileName))
var fileExtension = payload.Where(x => x.Key == "content" && x.Value == "pdf").SingleOrDefault().Value;
if (!string.IsNullOrEmpty(fileExtension))
{
var contentDisposition = response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
};
}

// pdf
fileName = payload.Where(x => x.Key == "instrument").SingleOrDefault().Value;
// to do , make extensions for various types
// save the file to a specified location using an extension method
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);

if (!string.IsNullOrEmpty(pathValue))
{
var fileExtension = payload.Where(x => x.Key == "content" && x.Value == "pdf").SingleOrDefault().Value;
if (!string.IsNullOrEmpty(fileExtension))
{
// pdf
fileName = payload.Where(x => x.Key == "instrument").SingleOrDefault().Value;
// to do , make extensions for various types
// save the file to a specified location using an extension method
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);

}
else
{
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);

}
_responseMessage = fileName;
}
else
{
_responseMessage = await response.Content.ReadAsStringAsync();
await response.Content.ReadAsFileAsync(fileName, pathValue, true, fileExtension);

}
_responseMessage = fileName;
}
else
{
_responseMessage = await response.Content.ReadAsStringAsync();
}
}
else
{
_responseMessage = await response.Content.ReadAsStringAsync();
}
}

}
return _responseMessage;
}
Expand All @@ -781,14 +722,13 @@ public static async Task<string> SendPostRequestAsync(this RedcapApi redcapApi,
Log.Error($"{Ex.Message}");
return Empty;
}
}
/// <summary>
/// Sends http request to api
/// </summary>
/// <param name="redcapApi"></param>
/// <param name="payload">data </param>
/// <param name="uri">URI of the api instance</param>
/// <returns>string</returns>
} /// <summary>
/// Sends http request to api
/// </summary>
/// <param name="redcapApi"></param>
/// <param name="payload">data </param>
/// <param name="uri">URI of the api instance</param>
/// <returns>string</returns>
public static async Task<string> SendPostRequest(this RedcapApi redcapApi, Dictionary<string, string> payload, Uri uri)
{
string responseString;
Expand Down
Loading

0 comments on commit cd69557

Please sign in to comment.