Get the ID of file just streamed to SharePoint Document Folder - c#

Please read the bottom of this post, since the question has been modified.
I have been successful in taking a file off of my computer and sending it to a document library in SharePoint. However, the "Title" column in the document is blank. I would like to set the "Title" column to a certain value, but not sure how to go about it.
Here is the code I use to upload the file
public static async Task PutFileAsync()
{
string genName = App.Generator;
genName = genName.Replace(" ", "-");
StorageLibrary videoLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
string readFolder = videoLibrary.SaveFolder.Path;
StorageFolder videoFolder = await StorageFolder.GetFolderFromPathAsync(readFolder);
string readFileName = App.Date + "-" + App.StartTime + "-" + App.IBX + "-" + genName + ".xlsx";
StorageFile readFile = await videoFolder.GetFileAsync(readFileName);
byte[] result;
using (Stream stream = await readFile.OpenStreamForReadAsync())
{
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
result = memoryStream.ToArray();
}
}
var (authResult, message) = await Authentication.AquireTokenAsync();
var httpClient = new HttpClient();
HttpResponseMessage response;
string posturl = MainPage.spfileurl + readFile.Name + ":/content";
var request = new HttpRequestMessage(HttpMethod.Put, posturl);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
request.Content = new ByteArrayContent(result);
response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
await Task.Run(() =>
{
File.Delete(readFile.Path);
return TaskStatus.RanToCompletion;
});
}
Any suggestions would be great!
Thanks!
Other information
public static string rooturl = "https://graph.microsoft.com/v1.0/sites/mycompanyinc.sharepoint.com,495435b4-60c3-49b7-8f6e-1d262a120ae5,0fad9f67-35a8-4c0b-892e-113084058c0a/";
string submiturl = rooturl + "lists/18a725ac-83ef-48fb-a5cb-950ca2378fd0/items";
public static string spfileurl = rooturl + "drive/root:/Generator_Runs/";
public static string fileurl = rooturl + "lists/edd49389-7edb-41db-80bd-c8493234eafa/drive/items/01JDP7KXPY64K4C3P4YJC2CJ2IUFG7DAP7/content";
Since it is not possible to add column data while uploading, I need to figure out what the listitem ID is for the file that I just uploaded is.
This is the responseString after the submission
[JSON]
#odata.context: "https://graph.microsoft.com/v1.0/$metadata#sites('mycompanyinc.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/drive/root/$entity"
#microsoft.graph.downloadUrl: "https://mycompanyinc.sharepoint.com/sites/GeneratorApp/_layouts/15/download.aspx?UniqueId=...&ApiVersion=2.0"
createdDateTime: "12/29/2018 6:43:00 PM"
eTag: ""{BB51689A-9FF5-412C-8B45-D01D2B61A789},2""
id: "01JDP7KXM2NBI3X5M7FRAYWROQDUVWDJ4J"
lastModifiedDateTime: "12/29/2018 6:43:00 PM"
name: "FileNameJ.xlsx"
webUrl: "https://mycompanyinc.sharepoint.com/sites/GeneratorApp/_layouts/15/Doc.aspx?sourcedoc=%7BBB51689A-9FF5-412C-8B45-D01D2B61A789%7D&file=FileName.xlsx&action=default&mobileredirect=true"
cTag: ""c:{BB51689A-9FF5-412C-8B45-D01D2B61A789},4""
size: 47079
createdBy
lastModifiedBy
parentReference
file
fileSystemInfo

Okay, it took a lot of trial and error. I had to create another class to be able to parse out the data:
public class SharePointDocumentNew
{
public class RootObject
{
public string eTag { get; set; }
public string id { get; set; }
public string name { get; set; }
public string webUrl { get; set; }
}
}
AND
public class SharePointDocumentItems
{
public class Value
{
[JsonProperty("#odata.etag")]
public string OdataEtag { get; set; }
public string ETag { get; set; }
public string Id { get; set; }
public string WebUrl { get; set; }
}
public class RootObject
{
[JsonProperty("#odata.context")]
public string OdataContext { get; set; }
public List<Value> value { get; set; }
}
}
Then I found the matching data between the two and used REGEX to get the matching data with this code:
public static async Task PutFileAsync()
{
List<SharePointListItems.Lookup> Lookups = new List<SharePointListItems.Lookup>();
string genName = App.Generator;
genName = genName.Replace(" ", "-");
StorageLibrary videoLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos);
string readFolder = videoLibrary.SaveFolder.Path;
StorageFolder videoFolder = await StorageFolder.GetFolderFromPathAsync(readFolder);
string readFileName = App.Date + "-" + App.StartTime + "-" + App.IBX + "-" + genName + ".xlsx";
StorageFile readFile = await videoFolder.GetFileAsync(readFileName);
byte[] result;
using (Stream stream = await readFile.OpenStreamForReadAsync())
{
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
result = memoryStream.ToArray();
}
}
var (authResult, message) = await Authentication.AquireTokenAsync();
var httpClient = new HttpClient();
HttpResponseMessage response;
string posturl = MainPage.spfileurl + readFile.Name + ":/content";
var request = new HttpRequestMessage(HttpMethod.Put, posturl);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
request.Content = new ByteArrayContent(result);
response = await httpClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
JObject json = JObject.Parse(responseString);
var result3 = JsonConvert.DeserializeObject<SharePointDocumentNew.RootObject>(responseString);
eTag = result3.eTag.ToString();
eTag = eTag.Replace("\"{", "");
string replacement = "";
string endPattern = "}.*";
Regex rgxend = new Regex(endPattern);
eTag = rgxend.Replace(eTag, replacement);
eTag = Regex.Replace(eTag, #"[A-Z]+?", m => m.ToString().ToLower());
await Task.Run(() =>
{
File.Delete(readFile.Path);
return TaskStatus.RanToCompletion;
});
}
public static async Task GetFileDataAsync()
{
List<SharePointDocumentItems.Value> Value2 = new List<SharePointDocumentItems.Value>();
var (authResult2, message2) = await Authentication.AquireTokenAsync();
var httpClient2 = new HttpClient();
HttpResponseMessage response2;
string geturl = "https://graph.microsoft.com/v1.0/sites/mycoinc.sharepoint.com,495435b4-60c3-49b7-8f6e-1d262a120ae5,0fad9f67-35a8-4c0b-892e-113084058c0a/lists/edd49389-7edb-41db-80bd-c8493234eafa/items";
var request2 = new HttpRequestMessage(HttpMethod.Get, geturl);
request2.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult2.AccessToken);
response2 = await httpClient2.SendAsync(request2);
var responseString2 = await response2.Content.ReadAsStringAsync();
JObject json2 = JObject.Parse(responseString2);
var result2 = JsonConvert.DeserializeObject<SharePointDocumentItems.RootObject>(responseString2);
foreach (var d in result2.value)
{
string ETAG = d.ETag;
string startPattern = "^\\\"";
string replacement = "";
string endPattern = ",.*";
Regex rgxstart = new Regex(startPattern);
ETAG = rgxstart.Replace(ETAG, replacement);
Regex rgxend = new Regex(endPattern);
ETAG = rgxend.Replace(ETAG, replacement);
if (ETAG == eTag)
{
fileID = d.Id;
}
}
}
Now I have the ID I need to update the other columns associated with the file.

Related

Display Multiple JsonObject on Listview

I have a Json from the server as below:
{
"data": {
"komik_popular": {
"title": "Yei! Komik Awas Nyamuk Jahat jadi literasi terpopuler minggu ini lho!"
},
"buku_baru": {
"title": "Ada buku baru nih, Katalog Prasekolah"
}
},
}
I want to display the json on the listview, but I try Debug.Writeline("judul: " + highlight.Title) first
Code:
Highlight highlight = new Highlight();
string title = "";
string urlPath = link;
var httpClient = new HttpClient(new HttpClientHandler());
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("SCH-API-KEY", "SCH_KEnaBiDeplebt")
};
var response = await httpClient.PostAsync(urlPath, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
string jsonText = await response.Content.ReadAsStringAsync();
try
{
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonObject jsonData = jsonObject["data"].GetObject();
JsonObject bukuBObject = jsonData.ContainsKey("buku_baru") && jsonData["buku_baru"] != null ? jsonData["buku_baru"].GetObject() : JsonObject.Parse("");
try
{
title = bukuBObject["title"].GetString();
}
catch
{
}
JsonObject komikPObject = jsonData.ContainsKey("komik_popular") && jsonData["komik_popular"] != null ? jsonData["komik_popular"].GetObject() : JsonObject.Parse("");
try
{
title = komikPObject["title"].GetString();
}
catch
{
}
highlight.Title = title;
Debug.WriteLine("judul: " + highlight.Title);
}
Highlight.cs:
class Highlight
{
public string Title { get; set; }
}
I'm having a problem, when I try to debug only the title on "komik_popular" is displayed, I want all the data in "komik_popular" and "buku_baru" to be displayed. How to handle it?
private List<Highlight > HighlightList = new List<Highlight>();
string urlPath = link;
var httpClient = new HttpClient(new HttpClientHandler());
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("SCH-API-KEY", "SCH_KEnaBiDeplebt")
};
var response = await httpClient.PostAsync(urlPath, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
string jsonText = await response.Content.ReadAsStringAsync();
try
{
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonObject jsonData = jsonObject["data"].GetObject();
JsonObject komikPObject = jsonData.ContainsKey("komik_popular") && jsonData["komik_popular"] != null ? jsonData["komik_popular"].GetObject() : JsonObject.Parse("");
try
{
Highlight highlight = new Highlight();
string title = "";
title = komikPObject["title"].GetString();
HighlightList.Add(highlight);
}
catch
{
}
JsonObject bukuBObject = jsonData.ContainsKey("buku_baru") && jsonData["buku_baru"] != null ? jsonData["buku_baru"].GetObject() : JsonObject.Parse("");
try
{
Highlight highlight = new Highlight();
string title = "";
title = bukuBObject["title"].GetString();
HighlightList.Add(highlight);
}
catch
{
}
}
catch
{
}
foreach( Highlight items in HighlightList)
{
Debug.WriteLine("judul: " + items .Title);
}
}
for converting json data to list, first you have to create respective class model as per given data format after that you can convert or deserialize it in your list format , in cae of your json data you can follow below example :-
public class Titel
{
public string title { get; set; }
}
public class Data
{
public Titel komik_popular { get; set; }
public Titel buku_baru { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
class Program
{
static void Main(string[] args)
{
string s = "{'data':{'komik_popular':{'title':'Yei! Komik Awas Nyamuk Jahat jadi literasi terpopuler minggu ini lho!'},'buku_baru':{'title':'Ada buku baru nih, Katalog Prasekolah'}}}";
List<RootObject> dataList = JsonConvert.DeserializeObject<List<RootObject>>(s);
}
}

How do I stream a large file from api to api without using disk and running out of memory?

I have a API HTTPGET that retrieves a file from another API, and spits it out. This works for smaller files, but the problem I'm having is that the files retrieved can be rather large in size (up to 2gb), and the MemoryStream is a limitation. Any ideas how to stream the file content without using disk and avoiding the 'out of memory' exception?
Controller:
[Route("{id}/file", Name = "GetContentFile")]
[HttpGet]
public IHttpActionResult GetContentFile(string id)
{
if (String.IsNullOrEmpty(id))
return BadRequest();
ContentFile cfl = new ContentFile();
var ret = new HttpResponseMessage(HttpStatusCode.OK);
try
{
cfl = otcrepo.GetContentFile(id);
var mstream = new MemoryStream(cfl.Data);
ret.Content = new StreamContent(mstream);
ret.Content.Headers.ContentType = new MediaTypeHeaderValue(cfl.ContentType);
ret.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
}
catch
{
return InternalServerError();
}
if (cfl != null)
{
ResponseMessageResult responseMessageResult = ResponseMessage(ret);
return responseMessageResult;
}
else
{
return NotFound();
}
}
Model:
public class ContentFile
{
public string Filename { get; set; }
public byte[] Data { get; set; }
public StreamContent DataStream { get; set; }
public string ContentType { get; set; }
}
Repository call:
public ContentFile GetContentFile(string id)
{
ContentFile fl = new ContentFile();
using (var htc = new HttpClient())
{
var response = htc.GetAsync(ConfigurationManager.AppSettings["BaseUrl"] + "/api/v2/nodes/" + id + "/content/").Result;
fl.Data = response.Content.ReadAsByteArrayAsync().Result;
fl.ContentType = response.Content.Headers.GetValues("Content-Type").FirstOrDefault();
}
return fl;
}
Thanks.
So instead of GetContentFile reading the complete stream into an array and returning it we return the stream. Than there is no need for the MemoryStream.
[Route("{id}/file", Name = "GetContentFile")]
[HttpGet]
public async Task<IHttpActionResult> GetContentFile(string id)
{
...
var result = await otcrepo.GetContentFile(id);
ret.Content = new StreamContent(result.stream);
ret.Content.Headers.ContentType = new MediaTypeHeaderValue(result.contentType);
...
}
public async Task<(Stream stream, string contentType)> GetContentFile(string id)
{
var htc = new HttpClient()
var response = await htc.GetAsync(ConfigurationManager.AppSettings["BaseUrl"] + "/api/v2/nodes/" + id + "/content/");
var stream = await response.Content.ReadAsStreamAsync();
var contentType = response.Content.Headers.GetValues("Content-Type").FirstOrDefault();
return (stream, contentType);
}

how to add multiple items in the model in the mvc

i have 2 devices , each device having 10 lattitude and 10 longitude values. im having 2 devices which has 10 lat long values of each , but only 10 items are adding another 10 items of device 2 data are getting replaced in the model. how to add 2 devices data in the model like this without creating 2 different classes for each.
im accessing the model values in the view like this
#Model[0].latitude.ToString()....#Model[9].latitude.ToString(),
#Model[1].longitude.ToString()....#Model[9].latitude.ToString(),
i should be able to access the 2 different devices data in the view like this
#Model[0][0]...[0][9];
#Model[1][0]...[1][9];
code
public ActionResult Index()
{
List<AssetTrackerViewModel> model = new List<AssetTrackerViewModel>();
model.AddRange(getAssetDetails("ED"));
model.AddRange(getAssetDetails("EE"));
return View(model);
}
private List<AssetTrackerViewModel> getAssetDetails(string deviceID)
{
List<AssetTrackerViewModel> model = new List<AssetTrackerViewModel>();
try
{
WebRequest req = WebRequest.Create(#"url");
req.Method = "GET";
req.Headers["Authorization"] = "Basic " + "a2VybmVsc3BoZXJlOmtlcm5lbHNwaGVyZQ==";
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
var encoding = resp.CharacterSet == "" ? Encoding.UTF8 : Encoding.GetEncoding(resp.CharacterSet);
using (var stream = resp.GetResponseStream())
{
var reader = new StreamReader(stream, encoding);
var responseString = reader.ReadToEnd();
var Pirs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AssetDetail>>(responseString);
var items = Pirs.Where(a => !a.dataFrame.EndsWith("AAAAAAAAAAA="))
.GroupBy(a => a.dataFrame.Substring(a.dataFrame.Length - 12))
.Select(g => g.First()) .OrderByDescending(a => a.timestamp).Take(10);
foreach (var item in items)
{
byte[] data = Convert.FromBase64String(item.dataFrame.ToString());
string hex = BitConverter.ToString(data);//converting base 64 to hexcode
string formattedHex = BitConverter.ToString(data).Replace(#"-", string.Empty);
string longitude = formattedHex.Substring(14, formattedHex.Length - 14);//04AC07EB
long longitudeValue = Convert.ToInt64(longitude, 16);
string longvalue = longitudeValue.ToString();
longvalue = longvalue.Insert(2, ".");
string latitude = formattedHex.Substring(6, formattedHex.Length - 14); //010A366B
long lat = Convert.ToInt64(latitude, 16);
string latvalue = lat.ToString();
latvalue = latvalue.Insert(2, ".");
AssetTrackerViewModel assetModel = new AssetTrackerViewModel();
assetModel.deviceid = deviceID;
assetModel.latitude = latvalue;
assetModel.longitude = longvalue;
model.Add(assetModel);
}
}
}
return model;
}
view model
public class AssetDetail
{
public long id { get; set; }
public DateTime timestamp { get; set; }
public string dataFrame { get; set; }
}
Modify you classes:
// this is class that represents single device
public class AssetTracker
{
public AssetTracker()
{
latitude = new List<string>();
longitude = new List<string>();
}
public string deviceid {get; set;}
public List<string> latitude {get; set;}
public List<string> longitude {get; set;}
}
Then you viewmodel:
public class AssetTrackersViewModel
{
public AssetTrackersViewModel()
{
AssetTrackers = new List<AssetTracker>();
}
public List<AssetTracker> AssetTrackers {get;set}
}
Then your getAssetDetails method:
private AssetTracker getAssetDetails(string deviceID)
{
var assetTracker = new AssetTracker { deviceid = deviceID };
try
{
WebRequest req = WebRequest.Create(#"url");
req.Method = "GET";
req.Headers["Authorization"] = "Basic " + "a2VybmVsc3BoZXJlOmtlcm5lbHNwaGVyZQ==";
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
var encoding = resp.CharacterSet == "" ? Encoding.UTF8 : Encoding.GetEncoding(resp.CharacterSet);
using (var stream = resp.GetResponseStream())
{
var reader = new StreamReader(stream, encoding);
var responseString = reader.ReadToEnd();
var Pirs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AssetDetail>>(responseString);
var items = Pirs.Where(a => !a.dataFrame.EndsWith("AAAAAAAAAAA="))
.GroupBy(a => a.dataFrame.Substring(a.dataFrame.Length - 12))
.Select(g => g.First()) .OrderByDescending(a => a.timestamp).Take(10);
foreach (var item in items)
{
byte[] data = Convert.FromBase64String(item.dataFrame.ToString());
string hex = BitConverter.ToString(data);//converting base 64 to hexcode
string formattedHex = BitConverter.ToString(data).Replace(#"-", string.Empty);
string longitude = formattedHex.Substring(14, formattedHex.Length - 14);//04AC07EB
long longitudeValue = Convert.ToInt64(longitude, 16);
string longvalue = longitudeValue.ToString();
longvalue = longvalue.Insert(2, ".");
string latitude = formattedHex.Substring(6, formattedHex.Length - 14); //010A366B
long lat = Convert.ToInt64(latitude, 16);
string latvalue = lat.ToString();
latvalue = latvalue.Insert(2, ".");
assetTracker.latitude.Add(latvalue);
assetTracker.longitude.Add(longvalue);
}
return assetTracker;
}
}
}
Then:
public ActionResult Index()
{
var model = new AssetTrackersViewModel();
model.AssetTrackers.Add(getAssetDetails("ED"));
model.AssetTrackers.Add(getAssetDetails("EE"));
return View(model);
}
Then, you can call in Razor:
#model AssetTrackersViewModel
for first 'device'
#Model.AssetTrackers[0].latitude[0]
#Model.AssetTrackers[0].longitude[0]
#Model.AssetTrackers[0].latitude[9]
#Model.AssetTrackers[0].longitude[9]
for second 'device'
#Model.AssetTrackers[1].latitude[0]
#Model.AssetTrackers[1].longitude[0]
#Model.AssetTrackers[1].latitude[9]
#Model.AssetTrackers[1].longitude[9]

How can I get data from a HTTP post in C# Xamarin?

I am trying to POST some data using HTTPClient. I have managed to use the following code when simply getting data in JSON format, but it doesn't seem to work for a POST.
This is the code I'm using:
public static async Task<SwipeDetails> SaveSwipesToCloud()
{
//get unuploaded swips
IEnumerable<SwipeDetails> swipesnotsved = SwipeRepository.GetUnUploadedSwipes();
foreach (var item in swipesnotsved)
{
//send it to the cloud
Uri uri = new Uri(URL + "SaveSwipeToServer" + "?locationId=" + item.LocationID + "&userId=" + item.AppUserID + "&ebCounter=" + item.SwipeID + "&dateTimeTicks=" + item.DateTimeTicks + "&swipeDirection=" + item.SwipeDirection + "&serverTime=" + item.IsServerTime );
HttpClient myClient = new HttpClient();
var response = await myClient.GetAsync(uri);
//the content needs to update the record in the SwipeDetails table to say that it has been saved.
var content = await response.Content.ReadAsStringAsync();
}
return null;
}
This is the method it's trying to contact. As you can see, the method also returns some data in JSON format so as well as a POST it's also getting some data back which I need to be able to work with:
[HttpPost]
public JsonResult SaveSwipeToServer(int locationId, int userId, int ebCounter, long dateTimeTicks, int swipeDirection, int serverTime)
{
bool result = false;
string errMsg = String.Empty;
int livePunchId = 0;
int backupPunchId = 0;
IClockPunch punch = null;
try
{
punch = new ClockPunch()
{
LocationID = locationId,
Swiper_UserId = userId,
UserID = ebCounter,
ClockInDateTime = DateTimeJavaScript.ConvertJavascriptDateTime(dateTimeTicks),
ClockedIn = swipeDirection.Equals(1),
};
using (IDataAccessLayer dal = DataFactory.GetFactory())
{
DataAccessResult dalResult = dal.CreatePunchForNFCAPI(punch, out livePunchId, out backupPunchId);
if (!dalResult.Result.Equals(Result.Success))
{
throw dalResult.Exception;
}
}
result = true;
}
catch (Exception ex)
{
errMsg = "Something Appeared to go wrong when saving punch information to the horizon database.\r" + ex.Message;
}
return Json(new
{
result = result,
punchDetails = punch,
LivePunchId = livePunchId,
BackUpPunchId = backupPunchId,
timeTicks = DateTimeJavaScript.ToJavaScriptMilliseconds(DateTime.UtcNow),
errorMessage = errMsg
}
,JsonRequestBehavior.AllowGet);
}
At the moment the data being stored in 'content' is just an error message.
You can post the parameters in the body of the request.
public static async Task<SwipeDetails> SaveSwipesToCloud() {
//get unuploaded swips
var swipesnotsved = SwipeRepository.GetUnUploadedSwipes();
var client = new HttpClient() {
BaseAddress = new Uri(URL)
};
var requestUri = "SaveSwipeToServer";
//send it to the cloud
foreach (var item in swipesnotsved) {
//create the parameteres
var data = new Dictionary<string, string>();
data["locationId"] = item.LocationID;
data["userId"] = item.AppUserID;
data["ebCounter"] = item.SwipeID;
data["dateTimeTicks"] = item.DateTimeTicks;
data["swipeDirection"] = item.SwipeDirection;
data["serverTime"] = item.IsServerTime;
var body = new System.Net.Http.FormUrlEncodedContent(data);
var response = await client.PostAsync(requestUri, body);
//the content needs to update the record in the SwipeDetails table to say that it has been saved.
var content = await response.Content.ReadAsStringAsync();
}
return null;
}
I am not sure how you host your service, it is not clear from your code. I hosted mine in Web API controller SwipesController in application HttpClientPostWebService. I don't suggest to use JsonResult. For mobile client I would just return the class you need.
You have 2 options:
Use get not post.
Use post.
Both cases are below
Controller:
namespace HttpClientPostWebService.Controllers
{
public class SwipesController : ApiController
{
[System.Web.Http.HttpGet]
public IHttpActionResult SaveSwipeToServer(int locationId, int userId, int ebCounter, long dateTimeTicks, int swipeDirection, int serverTime)
{
return Ok(new SwipeResponse
{
TestInt = 3,
TestString = "Testing..."
});
}
[System.Web.Http.HttpPost]
public IHttpActionResult PostSwipeToServer([FromBody] SwipeRequest req)
{
return Ok(new SwipeResponse
{
TestInt = 3,
TestString = "Testing..."
});
}
}
public class SwipeRequest
{
public string TestStringRequest { get; set; }
public int TestIntRequest { get; set; }
}
public class SwipeResponse
{
public string TestString { get; set; }
public int TestInt { get; set; }
}
}
Client:
async private void Btn_Clicked(object sender, System.EventArgs e)
{
HttpClient client = new HttpClient();
try
{
var result = await client.GetAsync(#"http://uri/HttpClientPostWebService/Api/Swipes?locationId=1&userId=2&ebCounter=3&dateTimeTicks=4&swipeDirection=5&serverTime=6");
var content = await result.Content.ReadAsStringAsync();
var resp = JsonConvert.DeserializeObject<SwipeResponse>(content);
}
catch (Exception ex)
{
}
try
{
var result1 = await client.PostAsync(#"http://uri/HttpClientPostWebService/Api/Swipes",
new StringContent(JsonConvert.SerializeObject(new SwipeRequest() { TestIntRequest = 5, TestStringRequest = "request" }), Encoding.UTF8, "application/json"));
var content1 = await result1.Content.ReadAsStringAsync();
var resp1 = JsonConvert.DeserializeObject<SwipeResponse>(content1);
}
catch (Exception ex)
{
}
}

Convert JSON data to querystring in C# GET request

What is the best way to convert a JSON object into querystrings to append to a GET Url? The POST is straight forward and gets read by my Web API backend.
{Name: 'Mike' } = ?Name=Mike
private static string MakeRequest(HttpWebRequest req, string data)
{
try
{
if (req.Method == Verbs.POST.ToString() || req.Method == Verbs.PUT.ToString() || req.Method == Verbs.DELETE.ToString())
{
var encodedData = Encoding.UTF8.GetBytes(data);
req.ContentLength = encodedData.Length;
req.ContentType = "application/json";
req.GetRequestStream().Write(encodedData, 0, encodedData.Length);
}
using (var response = req.GetResponse() as HttpWebResponse)
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
catch (WebException we)
{
if(we.Response == null)
{
return JsonConvert.SerializeObject(new { Errors = new List<ApiError> { new ApiError(11, "API is currently unavailable") }});
}
using (var response = we.Response as HttpWebResponse)
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
}
If the json object is flat as in your example, then
string json = #"{
""name"": ""charlie"",
""num"": 123
}";
var jObj = (JObject)JsonConvert.DeserializeObject(json);
var query = String.Join("&",
jObj.Children().Cast<JProperty>()
.Select(jp=>jp.Name + "=" + HttpUtility.UrlEncode(jp.Value.ToString())));
query would be name=charlie&num=123
I make this code to run in .Net Core:
public static string JsonToQuery(this string jsonQuery)
{
string str = "?";
str += jsonQuery.Replace(":", "=").Replace("{","").
Replace("}", "").Replace(",","&").
Replace("\"", "");
return str;
}
Example:
var _baseURI = "http://www.example.com/";
var endPoint = "myendpoint";
ExampleObjectModel requestModel = new ExampleObjectModel();
var requestModelJson = JsonConvert.SerializeObject(requestModel);
var url = string.Format("{0}{1}{2}", _baseURI, endPoint, requestModelJson.JsonToQuery());
Try this, work all object, in deep
public static class ExtensionMethods
{
public static string GetQueryString(this object obj, string prefix = "")
{
var query = "";
try
{
var vQueryString = (JsonConvert.SerializeObject(obj));
var jObj = (JObject)JsonConvert.DeserializeObject(vQueryString);
query = String.Join("&",
jObj.Children().Cast<JProperty>()
.Select(jp =>
{
if (jp.Value.Type == JTokenType.Array)
{
var count = 0;
var arrValue = String.Join("&", jp.Value.ToList().Select<JToken, string>(p =>
{
var tmp = JsonConvert.DeserializeObject(p.ToString()).GetQueryString(jp.Name + HttpUtility.UrlEncode("[") + count++ + HttpUtility.UrlEncode("]"));
return tmp;
}));
return arrValue;
}
else
return (prefix.Length > 0 ? prefix + HttpUtility.UrlEncode("[") + jp.Name + HttpUtility.UrlEncode("]") : jp.Name) + "=" + HttpUtility.UrlEncode(jp.Value.ToString());
}
)) ?? "";
}
catch (Exception ex)
{
}
return query;
}
}
To use: SomeObject.GetQueryString();
if your object(Entity) have a Children like this Entity :
public class Parent
{
public Child childs { get; set; } = new Child();
public int PageIndex { get; set; }
public int? PageSize { get; set; }
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
}
Your Can Use This Code For Build Query:
First Convert You Enrity Model To JObject
And Call This Method :
public static string GetQueryString(this JObject jObj)
{
return String.Join("&",
jObj.Children().Cast<JProperty>()
.Select(jp =>
{
if (jp.Value.Type == JTokenType.Object)
{
var arrValue = String.Join("&",
jObj.Values().Children().Cast<JProperty>()
.Select(jp => jp.Path + "=" + HttpUtility.UrlEncode(jp.Value.ToString())));
return arrValue;
}
else
{
var arrValue = String.Join("&", jp.Name + "=" + HttpUtility.UrlEncode(jp.Value.ToString()));
return arrValue;
}
}
)) ?? "";
}
Your Can Get Like This QueryString :
childs.Id=1&childs.Name="Test"&PageIndex=1&PageSize=1

Categories