WebSocket API for Bitfinex by C# code - c#

I take data from Bittrex without WebSocket by this way
request = WebRequest.Create("https://bittrex.com/api/v1.1/public/getticker?market=USDT-BTC");
request.Credentials = CredentialCache.DefaultCredentials;
response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
date = JsonConvert.DeserializeObject(responseFromServer);
It is very easy way and it is working on Bittrex. But I did a lot off request. I need do it on Bitfinex but I have the exeption "Too many request". As I understood I need WebSocket for this. By this adress https://api.bitfinex.com/v1/pubticker/BTCUSD. Somebody can show easy code to understand how I need to conect and write in Console info from WebSocket. Thanks!

BIttrex release in March beta version of new site and WebSocket. GitHub repository have samples for usage WebSocket channel to subscribe for events.
Here is C# example:
using System;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using Microsoft.AspNet.SignalR.Client;
namespace WebsocketSample
{
public sealed class BittrexWebsocket
{
public delegate void BittrexCallback(string info);
private HubConnection _hubConnection { get; }
private IHubProxy _hubProxy { get; }
private BittrexCallback _updateExchangeState { get; }
private BittrexCallback _updateOrderState { get; }
private BittrexCallback _updateBalanceState { get; }
public BittrexWebsocket(
string connectionUrl,
BittrexCallback updateExchangeState,
BittrexCallback updateOrderState,
BittrexCallback updateBalanceState
)
{
// Set delegates
_updateExchangeState = updateExchangeState;
_updateOrderState = updateOrderState;
_updateBalanceState = updateBalanceState;
// Create connection to c2 SignalR hub
_hubConnection = new HubConnection(connectionUrl);
_hubProxy = _hubConnection.CreateHubProxy("c2");
// Register callback for uE (exchange state delta) events
_hubProxy.On(
"uE",
exchangeStateDelta => _updateExchangeState?.Invoke(exchangeStateDelta)
);
// Register callback for uO (order status change) events
_hubProxy.On(
"uO",
orderStateDelta => _updateOrderState?.Invoke(orderStateDelta)
);
// Register callback for uB (balance status change) events
_hubProxy.On(
"uB",
balanceStateDelta => _updateBalanceState?.Invoke(balanceStateDelta)
);
_hubConnection.Start().Wait();
}
public void Shutdown() => _hubConnection.Stop();
// marketName example: "BTC-LTC"
public async Task<bool> SubscribeToExchangeDeltas(string marketName) => await _hubProxy.Invoke<bool>("SubscribeToExchangeDeltas", marketName);
// The return of GetAuthContext is a challenge string. Call CreateSignature(apiSecret, challenge)
// for the response to the challenge, and pass it to Authenticate().
public async Task<string> GetAuthContext(string apiKey) => await _hubProxy.Invoke<string>("GetAuthContext", apiKey);
public async Task<bool> Authenticate(string apiKey, string signedChallenge) => await _hubProxy.Invoke<bool>("Authenticate", apiKey, signedChallenge);
// Decode converts Bittrex CoreHub2 socket wire protocol data into JSON.
// Data goes from base64 encoded to gzip (byte[]) to minifed JSON.
public static string Decode(string wireData)
{
// Step 1: Base64 decode the wire data into a gzip blob
byte[] gzipData = Convert.FromBase64String(wireData);
// Step 2: Decompress gzip blob into minified JSON
using (var decompressedStream = new MemoryStream())
using (var compressedStream = new MemoryStream(gzipData))
using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
deflateStream.CopyTo(decompressedStream);
decompressedStream.Position = 0;
using (var streamReader = new StreamReader(decompressedStream))
{
return streamReader.ReadToEnd();
}
}
}
public static string CreateSignature(string apiSecret, string challenge)
{
// Get hash by using apiSecret as key, and challenge as data
var hmacSha512 = new HMACSHA512(Encoding.ASCII.GetBytes(apiSecret));
var hash = hmacSha512.ComputeHash(Encoding.ASCII.GetBytes(challenge));
return BitConverter.ToString(hash).Replace("-", string.Empty);
}
}
class Program
{
static public BittrexWebsocket.BittrexCallback CreateCallback(string name)
{
//
// In a real app, your code would do something useful based on the
// information accompanying each event.
//
return (info) =>
{
Console.WriteLine($"Callback Invoked: {name}");
Console.WriteLine(
BittrexWebsocket.Decode(info)
);
};
}
static void Main(string[] args)
{
Task task = Task.Run(
async () =>
{
string apiKey = "YOUR_API_KEY";
string apiSecret = "YOUR_API_SECRET";
string baseUrl = "https://beta.bittrex.com/signalr";
var btx = new BittrexWebsocket(
baseUrl,
CreateCallback("exchange"),
CreateCallback("order"),
CreateCallback("balance")
);
// If we successfully authenticate, we'll be subscribed to the uO and uB events.
var isAuthenticated = await btx.Authenticate(
apiKey,
BittrexWebsocket.CreateSignature(apiSecret, await btx.GetAuthContext(apiKey))
);
// Register for orderbook updates on the BTC-ETH market
await btx.SubscribeToExchangeDeltas("BTC-ETH");
});
task.Wait();
Console.WriteLine("Press enter to exit sample...");
Console.ReadLine();
}
}
}
Run in PackageManager Console to add SignalR dependency:
Install-Package Microsoft.AspNet.SignalR.Client -Version 2.3.0
Also to connect you need get Key and Secret from your account on Bittrex.
string apiKey = "YOUR_API_KEY";
string apiSecret = "YOUR_API_SECRET";
For Bitfinex you can try next code:
using System;
using WebSocketSharp;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
using (var ws = new WebSocket("wss://api.bitfinex.com/ws/2"))
{
ws.OnMessage += (sender, e) => Console.WriteLine(e.Data);
ws.Connect();
ws.Send("{\"event\":\"subscribe\", \"channel\":\"ticker\", \"pair\":\"BTCUSD\"}");
Console.ReadKey(true);
}
}
}
}
Requires dependency from Nuget:
Install-Package WebSocketSharp-NonPreRelease -Version 1.0.0

Related

Consume a Web Service in C#: Remove Task.Wait()

I am trying to consume a web service. It's an XML based service. I mean response in XML format. The code is working fine. However, I do not want to use task.Wait(). Please let me know how I can replace it with async/await.
Below is my code :
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
Program obj = new Program();
var result = obj.GetData().Result;
}
public async Task<string> GetData()
{
string url =
"https://test.net/info.php?akey=abcd&skey=xyz";
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(url).Result;
var responseValue = string.Empty;
if (response != null)
{
Task task = response.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
});
task.Wait(); // How I can replace it and use await
}
return responseValue;
}
}
[XmlRoot(ElementName = "Info")]
public class Test
{
[XmlAttribute(AttributeName = "att")]
public string SomeAttribute{ get; set; }
[XmlText]
public string SomeText{ get; set; }
}
}
You already are in an async context, so just use await:
var stream = await response.Content.ReadAsStreamAsync();
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
That said, you should check all your calls:
HttpResponseMessage response = await client.GetAsync(url);
and make your main async, too and while we are at it make the method static:
public static async Task Main)
{
var result = await GetData();
}
where your method signature is:
public static async Task<string> GetData()
The static isn't required, but you will find parallel and/or asynchronous programming is a lot easier if you have as little side effects as possible.
You can make Main method async as well and await GetData
static async Task Main(string[] args)
{
Program obj = new Program();
var result = await obj.GetData();
}

Best way to setup MSTest for REST service with cookie-authentication?

Background: I am using ASP.NET Core 3.1, and integration testing a REST service that requires cookie authentication.
Candidate solution below.
Note:
The reason I use a vanilla Host instead of TestServer is because of the cookie requirement. When using TestServer, it provides an HttpClient for you, but the client does not pass cookies back to the server.
I also attempted to use a custom HttpClient with TestServer. That consistently generated a System.Net.Sockets.SocketException (No connection could be made because the target machine actively refused it.)
using Microsoft.Extensions.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using WebApi; // Contains my Startup.cs
namespace WebApiTest
{
[TestClass]
public class UserTest
{
static IHost HttpHost;
[ClassInitialize]
public static async Task ClassStartup(TestContext context)
{
HttpHost = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.Build();
await HttpHost.StartAsync();
}
[ClassCleanup]
public static async Task ClassCleanup()
{
await HttpHost.StopAsync();
}
public static HttpContent GetHttpContent(object content)
{
HttpContent httpContent = null;
if (content != null)
{
httpContent = new ByteArrayContent(JsonSerializer.SerializeToUtf8Bytes(content, content.GetType()));
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
}
return httpContent;
}
public static HttpClient GetCookieHttpClient()
{
SocketsHttpHandler handler = new SocketsHttpHandler
{
AllowAutoRedirect = false,
CookieContainer = new CookieContainer(),
UseCookies = true
};
return new HttpClient(handler);
}
[TestMethod]
public async Task GetUserData_ReturnsSuccess()
{
using (HttpClient client = GetCookieHttpClient())
{
var credentials = new
{
Email = "test#test.com",
Password = "password123",
};
HttpResponseMessage response = await client.PostAsync("http://localhost:5000/api/auth/login", GetHttpContent(credentials));
response = await client.GetAsync(String.Format("http://localhost:5000/api/users/{0}", credentials.Email));
Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
}
}
}
}
HttpClient is a thin-client; it doesn't do anything unless you explicitly tell it to. In other words, it will never send the cookie for you; you must add a Cookie header to the request with the cookie value for each request. The test server "client" is just an HttpClient instance set up to proxy requests to the test server. You should use the test server, as prescribed, along with its client, and then add the Cookie header the requests you make with that.
Solutions based on Chris Pratt's suggestions
After some further digging, Microsoft provides a solution for this (WebApplicationFactory):
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using WebApi;
namespace WebApiTest
{
[TestClass]
public class Class2
{
static WebApplicationFactory<Startup> Factory;
static WebApplicationFactoryClientOptions ClientOptions;
[ClassInitialize]
public static async Task ClassStartup(TestContext context)
{
Factory = new WebApplicationFactory<Startup>();
ClientOptions = new WebApplicationFactoryClientOptions();
ClientOptions.AllowAutoRedirect = false;
ClientOptions.HandleCookies = true;
ClientOptions.BaseAddress = new Uri("http://localhost:5000");
}
public static HttpContent GetHttpContent(object content)
{
HttpContent httpContent = null;
if (content != null)
{
httpContent = new ByteArrayContent(JsonSerializer.SerializeToUtf8Bytes(content, content.GetType()));
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
}
return httpContent;
}
[TestMethod]
public async Task GetUserData_ReturnsSuccess()
{
using (HttpClient client = Factory.CreateClient(ClientOptions))
{
var credentials = new
{
Email = "test#test.com",
Password = "password123",
};
HttpResponseMessage response = await client.PostAsync("http://localhost:5000/api/auth/login", GetHttpContent(credentials));
response = await client.GetAsync(String.Format("http://localhost:5000/api/users/{0}", credentials.Email));
Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
}
}
}
}
In case you want to stick with TestServer, here is a manual Cookie-passing implementation:
using Microsoft.AspNetCore.TestHost;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using WebApi;
namespace WebApiTest
{
public class CookieHttpClient : IDisposable
{
private static HttpContent GetHttpContent(object content)
{
HttpContent httpContent = new ByteArrayContent(JsonSerializer.SerializeToUtf8Bytes(content, content.GetType()));
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return httpContent;
}
private static IEnumerable<string> GetCookieStrings(CookieCollection collection)
{
List<string> output = new List<string>(collection.Count);
foreach (Cookie cookie in collection)
{
output.Add(cookie.Name + "=" + cookie.Value);
}
return output;
}
private HttpClient client;
private CookieContainer container;
public CookieHttpClient(HttpClient client)
{
this.client = client;
this.container = new CookieContainer();
}
public async Task<HttpResponseMessage> SendAsync(HttpMethod method, Uri uri)
{
return await this.SendAsync(method, uri, null);
}
public async Task<HttpResponseMessage> SendAsync(HttpMethod method, Uri uri, object data)
{
HttpRequestMessage request = new HttpRequestMessage(method, uri);
// Add data
if (data != null)
{
request.Content = GetHttpContent(data);
}
// Add cookies
CookieCollection collection = this.container.GetCookies(uri);
if (collection.Count > 0)
{
request.Headers.Add("Cookie", GetCookieStrings(collection));
}
HttpResponseMessage response = await this.client.SendAsync(request);
// Remember cookies before returning
if (response.Headers.Contains("Set-Cookie"))
{
foreach (string s in response.Headers.GetValues("Set-Cookie"))
{
this.container.SetCookies(uri, s);
}
}
return response;
}
public void Dispose()
{
this.client.Dispose();
}
}
[TestClass]
public class Class1
{
static TestServer TestServer;
[ClassInitialize]
public static async Task ClassStartup(TestContext context)
{
IWebHostBuilder builder = new WebHostBuilder()
.UseStartup<Startup>();
TestServer = new TestServer(builder);
}
[TestMethod]
public async Task GetUserData_ReturnsSuccess()
{
using (CookieHttpClient client = new CookieHttpClient(TestServer.CreateClient()))
{
var credentials = new
{
Email = "test#test.com",
Password = "password123",
};
HttpResponseMessage response = await client.SendAsync(HttpMethod.Post, new Uri("http://localhost:5000/api/auth/login"), credentials);
response = await client.SendAsync(HttpMethod.Get, new Uri("http://localhost:5000/api/users/" + credentials.Email));
Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
}
}
}
}

Why do two (almost) similar methods(using c#) of uploading a file to Slack cause different outcomes?

so this question baffels me. I'll post quite abit of code to explain this one. First, I have and "old" version of code(c#), which I used to post messages and files to Slack. And this code works fine for me! The method of interest is the following:
public class PostMessage
{
private string _token = "xoxp-MyToken";
public string token { get { return _token; } }
public string channel { get; set; }
public string text { get; set; }
public MultipartFormDataContent UploadFile()
{
var requestContent = new MultipartFormDataContent();
var fileContent = new StreamContent(GetFile.ReadFile());
requestContent.Add(new StringContent(token), "token");
requestContent.Add(new StringContent(channel), "channels");
requestContent.Add(fileContent, "file", Path.GetFileName(GetFile.path));
return requestContent;
}
public static class GetFile
{
public static string path = #"C:\Users\f.held\Desktop\Held-Docs\Download.jpg";
public static FileStream ReadFile()
{
FileInfo fileInfo = new FileInfo(path);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
return fs;
}
}
Here is my client:
public class SlackClient
{
public Uri _method { get; set; }
private readonly HttpClient _httpClient = new HttpClient {};
public SlackClient(Uri webhookUrl)
{
_method = webhookUrl;
}
public async Task<HttpResponseMessage> UploadFileAsync(MultipartFormDataContent requestContent)
{
var response = await _httpClient.PostAsync(_method, requestContent);
return response;
}
}
And I call all of this in this Main:
public static void Main(string[] args)
{
Task.WaitAll(TalkToSlackAsync());
private static async Task TalkToSlackAsync()
{
var webhookUrl = new Uri("https://slack.com/api/files.upload");
var slackClient = new SlackClient(webhookUrl);
PostMessage PM = new PostMessage();
PM.channel = "DCW21NBHD";
var cont = PM.UploadFile();
var response = await slackClient.UploadFileAsync(cont);
string content = await response.Content.ReadAsStringAsync();
}
}
So far, so good! But now it gets interesting. I build a similar version, in which I use Newtonsoft's Json NuGet-package
Now, first the code:
the client:
public async Task<HttpResponseMessage> SendFileAsync(MultipartFormDataContent requestContent)
{
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "xoxp-MyToken");
var response = await _httpClient.PostAsync(UriMethod, requestContent);
return response;
}
the same Filestram-method for reading the file:
public class Message
{
public class GetFile // Just pass a path here as parameter!
{
public static string path = #"C:\Users\f.held\Desktop\Held-Docs\Download.jpg";
public static FileStream ReadFile()
{
FileInfo fileInfo = new FileInfo(path);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
return fs;
}
}
the Json-class which I serialize:
public class JsonObject
{
[JsonProperty("file")]
public string file { get; set; }
[JsonProperty("channels")]
public string channels { get; set; }
}
And the Main:
class MainArea
{
public static void Main( string[] args)
{
try
{
Task.WaitAll(SendMessage());
}
catch(Exception dudd)
{
Console.WriteLine(dudd);
Console.ReadKey();
}
}
private static async Task SendMessage()
{
var client = new BpsHttpClient("https://slack.com/api/files.upload");
JsonObject JO = new JsonObject();
JO.channels = "DCW21NBHD";
var Json = JsonConvert.SerializeObject(JO, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var StringJson = new StringContent(Json, Encoding.UTF8, "multipart/form-data");
var DeSon = JsonConvert.DeserializeObject(Json);
Console.WriteLine(DeSon);
Console.ReadKey();
var requestContent = new MultipartFormDataContent();
var fileContent = new StreamContent(Message.GetFile.ReadFile());
requestContent.Add(fileContent, "file", Path.GetFileName(Message.GetFile.path));
requestContent.Add(StringJson);
var ResponseFile = await client.SendFileAsync(requestContent);
Console.WriteLine(ResponseFile);
Console.ReadKey();
}
}
So, both SEEM to work. But the latter of these methods does NOT post the file to the declared channel - it merely uploads it to Slack. Which would be fine, because I could then work with the 'public_url' to publicise it on any channel. BUT - BIG BUT - with the first method, it immediately loads it to my channel! And it tells me so in the response I get from Slack. The responses are in both exactly the same - except for the timestamps and file_id etc. obviously. But the ending is different!
Here is the ending of the response from the old version:
"shares":{"private":{"DCW21NBHD":[{"reply_users":[],"reply_users_count":0,"reply_count":0,"ts":"1544025773.001700"}]}},"channels":[],"groups":[],"ims":["DCW21NBHD"]}}
and here is the answer from the new version:
"shares":{},"channels":[],"groups":[],"ims":[]}}
Okay now, why on god's green earth does one method do that and the other one does not? :D
Thanks to anybody who has some insight and knowledge on this specific "issue" and is willing to share!
As stated in the documentation for files.upload:
Present arguments as parameters in application/x-www-form-urlencoded
querystring or POST body. This method does not currently accept
application/json.
So the reason this does not work is that you are trying to provide the API parameters like channels as JSON, when this method does not support JSON. The result is that those properties are ignore, which is why the image is uploaded, but not shared in the designated channel.
To fix it simply provide your parameters as application/x-www-form-urlencoded querystring as you did in your 1st example.
Note that in general only a subset of the Slack API methods support using JSON for providing the parameters as listed here. If you want to use JSON, please double-check if the API method supports it, or stick with x-www-form-urlencoded (which is the standard for POST) to be on the safe side.

C# webapi POST via console program

I have a web api that I can access successfully through a browser :-
https://127.0.0.1:8443/ncrApi
I am trying to create a simple console program in C# using VS2015 to send data and receive a response using http POST.
Here is what I have so far:-
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace WebSample
{
class ApiSendData
{
public string UserID { get; set;} // username
public string Password { get; set;} // password for the webapi
public string ApiFunction { get; set; }
public string DppName { get; set; }
public string ClearData { get; set; }
public string DppVersion { get; set; }
}
class Program
{
static void Main(string[] args)
{
// The Main function calls an async method named RunAsync
// and then blocks until RunAsyncc completes.
RunAsync().Wait();
}
static async Task RunAsync()
{
using (var client = new HttpClient())
{
//specify to use TLS 1.2 as default connection
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
// This code sets the base URI for HTTP requests,
// and sets the Accept header to "application/json",
// which tells the server to send data in JSON format.
client.BaseAddress = new Uri("https://localhost:8443/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP POST
var datatobeSent = new ApiSendData()
{
UserID = "xxxx",
Password = "yyyy",
ApiFunction ="NcrSecureData",
DppName ="CSampleCustomer",
DppVersion ="Latest",
ClearData ="1234567890",
ResultType = "JSON"
};
HttpResponseMessage response = await client.PostAsJsonAsync("ncrApi", datatobeSent);
if (response.IsSuccessStatusCode)
{
// Get the URI of the created resource.
Uri ncrUrl = response.Headers.Location;
// do whatever you need to do here with the returned data //
}
}
}
}
}
In my response variable I get the 200 OK http 1.1 message, with content type = application/json and content-length = 174... but no actual data is received...
the variable ncrUrl is also null....
I am wondering if I need additional statements in my console program to receive the data?
Here is what I have been following:-
http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
Upon reading the comments it seems that your api is configured to return a file instead of a string content such as JSON or XML. You can use HttpContent.ReadAsStreamAsync Method to read the response stream and save it to a file.
HttpResponseMessage response = await client.PostAsJsonAsync("ncrApi", datatobeSent);
using (Stream output = File.OpenWrite("filename.txt")) // change
{
using (Stream input = await response.Content.ReadAsStreamAsync())
{
input.CopyTo(output);
}
}

Downloading XML from URL

I am trying to find a way to download an XML file on a windows phone which will later on be parsed to be used in a collection. Now I tried the same method I did with the WPF app which is:
public void downloadXml()
{
WebClient webClient = new WebClient();
Uri StudentUri = new Uri("url");
webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(fileDownloaded);
webClient.DownloadFileAsync(StudentUri, #"C:/path");
}
When moving it to the Windows Phone the webclient loses the DownloadFileAsync and DownloadFileCompleted function. So is there another way of doing this and will I have to use IsolatedStorageFile, if so how can a parse it?
I tried to reproduce your problem on my machine, but didn't find WebClient class at all. So I use WebRequest instead.
So, the first guy is the helper class for WebRequest:
public static class WebRequestExtensions
{
public static async Task<string> GetContentAsync(this WebRequest request)
{
WebResponse response = await request.GetResponseAsync();
using (var s = response.GetResponseStream())
{
using (var sr = new StreamReader(s))
{
return sr.ReadToEnd();
}
}
}
}
The second guy is the helper class for IsolatedStorageFile:
public static class IsolatedStorageFileExtensions
{
public static void WriteAllText(this IsolatedStorageFile storage, string fileName, string content)
{
using (var stream = storage.CreateFile(fileName))
{
using (var streamWriter = new StreamWriter(stream))
{
streamWriter.Write(content);
}
}
}
public static string ReadAllText(this IsolatedStorageFile storage, string fileName)
{
using (var stream = storage.OpenFile(fileName, FileMode.Open))
{
using (var streamReader = new StreamReader(stream))
{
return streamReader.ReadToEnd();
}
}
}
}
And the last piece of solution, the usage example:
private void Foo()
{
Uri StudentUri = new Uri("uri");
WebRequest request = WebRequest.Create(StudentUri);
Task<string> getContentTask = request.GetContentAsync();
getContentTask.ContinueWith(t =>
{
string content = t.Result;
// do whatever you want with downloaded contents
// you may save to isolated storage
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
storage.WriteAllText("Student.xml", content);
// you may read it!
string readContent = storage.ReadAllText("Student.xml");
var parsedEntity = YourParsingMethod(readContent);
});
// I'm doing my job
// in parallel
}
Hope this helps.

Categories