How to get the Download/Upload status(in %) from Http Client in Windows 8.1 Universal App? - windows-phone-8.1

I have a spec in which there is a need to ignore HTTPS certificates and also to get the status of Upload/Download.
I am using HttpClient to ignore the certificate but i could not find the way to get the status of downloading/Uploading.
I know it was there in WebClient Windows Phone 8 and Webclient not there in Windows 8.1.
So please guide me to accomplish both these things.

For Download progress, You can return response stream from your Http request and can use below code to write to file which also display progress status
IInputStream inputStream = null;
IRandomAccessStream fs = null;
try
{
inputStream = responseStream.AsInputStream();
ulong totalBytesRead = 0;
fs = await file.OpenAsync(FileAccessMode.ReadWrite);
ulong fileSize = Convert.ToUInt64(Size);
while (true)
{
// Read from the web.
if (!cancellationToken.IsCancellationRequested)
{
IBuffer buffer = new Windows.Storage.Streams.Buffer(512);
buffer = await inputStream.ReadAsync(
buffer,
buffer.Capacity,
InputStreamOptions.None);
if (buffer.Length == 0)
{
// There is nothing else to read.
break;
}
// Report progress.
totalBytesRead += buffer.Length;
double progress = ((double)totalBytesRead / fileSize);
double Value = progress * 100;
System.Diagnostics.Debug.WriteLine("Bytes read: {0}", totalBytesRead);
await fs.WriteAsync(buffer);
}
else
{
inputStream.Dispose();
fs.Dispose();
await file.DeleteAsync();
break;
}
}
inputStream.Dispose();
fs.Dispose();
}
catch
{
}
For upload Progress, there is no in built support to do that, but you can use
ProgressMessageHandler found in System.Net.Http.Handler which you can found on Nuget and than hook that to your HttpClient Object.

Related

My Windows Phone app Get empty response (404 Not Found) Scond time, work's great first time;And always work fine if without SSL

I am building my first windowsPhone 8.1 application ,the role of my application is to create connection with server to get information from it, so I am writing the code to do this process by sending json-rpc request to server to get some information ,I am successful to get it in first time but when I send the second request I am receiving an empty response with 404 error (page not found).
But when I call the service without https (http only) it works fine regardless how many time I call it !
public async Task<string> GetDataFromServer(string urlToCall, string JSONData,string RR)
{
string UserName = “XXXXXXX”
string Password = "XXX";
using ( var handler = new HttpClientHandler())
{
handler.Credentials = new NetworkCredential(UserName, Password);
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = null;
try
{
response = await client.PostAsync(urlToCall, new StringContent(JSONData.ToString(), Encoding.UTF8, " application/json"));
string res = response.Content.ReadAsStringAsync().Result;
Windows.UI.Popups.MessageDialog g = new Windows.UI.Popups.MessageDialog(res);
await g.ShowAsync();
return res;
}
catch (Exception ex)
{
Windows.UI.Popups.MessageDialog g = new Windows.UI.Popups.MessageDialog("Error is : " + ex.Message);
g.ShowAsync();
return "Error";
}
finally
{
response.Dispose();
client.CancelPendingRequests();
client.Dispose();
handler.Dispose();
}
}
}
Again, when call the URL of service (start with https) on first time I got response with seeked data, but second time I receive an empty response with 404 error (page not found) !!
Any help please
Please try to use this solution.
public async Task<string> SendJSONData3(string urlToCall, string JSONData)
{
string UserName = "XXXXXXXXX";
string Password = "XXXXXXXXX";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(urlToCall);
httpWebRequest.Credentials = new NetworkCredential(UserName, Password);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(await httpWebRequest.GetRequestStreamAsync()))
{
string json = JSONData;
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
A couple of ideas:
Do not use the .Result property. Just use await instead to avoid deadlocks.
Remove the additional space in front of the media type parameter " application/json"
Enable logging on the webserver and see if the second request arrives on the server.
Get a network trace, for example with Wireshark or Fiddler.
Try puting WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp); in your initialization code, as proposed in this answer.

http web server return zip file in a windows phone 8

hello i'm write a http web server in my app.
I used this code
http://developer.nokia.com/community/wiki/A_simplistic_HTTP_Server_on_Windows_Phone
this procedure works but not have a extentions of file in http response
return a file name without extention (.zip)
private async Task<StringBuilder> HandleRequest(StreamSocket socket)
{
//Initialize IO classes
DataReader reader = new DataReader(socket.InputStream);
reader.InputStreamOptions = InputStreamOptions.Partial;
DataWriter writer = new DataWriter(socket.OutputStream);
writer.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
//handle actual HTTP request
String request = await StreamReadLine(reader);
string[] tokens = request.Split(' ');
if (tokens.Length != 3)
{
throw new Exception("invalid http request line");
}
string httpMethod = tokens[0].ToUpper();
string httpUrl = tokens[1];
//read HTTP headers - contents ignored in this sample
while (!String.IsNullOrEmpty(await StreamReadLine(reader))) ;
try
{
if (httpUrl == "DOWNLOADZIP")
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
String content = null;
Stream stream;
byte[] data;
IsolatedStorageFileStream sri = storage.OpenFile("CompressedFiles.zip", FileMode.Open, FileAccess.Read);
if (null != sri)
{
stream = sri;
data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
writer.writebytes(data);
}
}
}
}
catch (Exception ex)//any exception leads to an Internal server error
{
writer.WriteString("HTTP/1.0 500 Internal server error\r\n");
writer.WriteString("Connection: close\r\n");
writer.WriteString("\r\n");
writer.WriteString(ex.Message);
}
}
await writer.StoreAsync();//write data actually to the network interface
socket.Dispose();
return null;
}
this is a solutions
ret.AppendLine("HTTP/1.0 200 OK");
ret.AppendLine("Content-Type: text/html");
ret.AppendLine("Connection: close");
ret.AppendLine("");
ret.AppendLine("Content-Disposition: attachment; filename=myfile.zip");

background Agent works fine in local environment but failed after app submission to app store

I have an wp8 app using PeriodicTask background Agent.
The task update the information of multiple live tiles,
using POST Client to get title and image url from my server to update the live tile.
Background agent works just fine in debugging and releasing mode. When the .xap file was deployed into my device using XAPDeployement tool, the background Agent also works perfectly.
However, it won't work after submitted to wp app store, no matter it's beta version or not.
If the app is downloaded from store, the background agent has never worked, and it is blocked by system after a few minutes.
How come it goes wrong since the XAP files are the same?
part of code:
public static Task<string> jsonPostClientTask(Dictionary<string, object> parameters, string url)
{
var results = new TaskCompletionSource<string>();
PostClient proxy = new PostClient(parameters);
try
{
proxy.DownloadStringCompleted += (sender, e) =>
{
if (e.Error == null)
{
string response = e.Result.ToString();
results.TrySetResult(response);
}
else
{
results.TrySetResult("");
results.TrySetException(e.Error);
}
};
proxy.DownloadStringAsync(new Uri(url));
}
catch
{
results.TrySetResult("");
}
return results.Task;
}
ScheduledAgent class:
protected override void OnInvoke(ScheduledTask task)
{
foreach (var tile in tileList)
{
string dataString = jsonPostClientTask(parameters, url);
//update tile in used
FlipTileData tileData = new FlipTileData()
{
BackContent = "string content",
WideBackContent = "string back content",
BackBackgroundImage = new Uri("http://xxxx.xxx/xxx.png", UriKind.RelativeOrAbsolute),
WideBackBackgroundImage = new Uri("http://xxxx.xxx/xxx.png", UriKind.RelativeOrAbsolute),
};
ShellTile primaryTile = ShellTile.ActiveTiles.First();
if (primaryTile != null)
primaryTile.Update(tileData);
}
}

How Upload Files on Server using WebClient Windows phone?

I want upload a file (any type) on a server.
I have my file which is saved like this (I use FileAssociation)
await SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "fileToSave" + fileext, NameCollisionOption.ReplaceExisting, NavigationContext.QueryString["filetoken"]);
Then I get the saved file
StorageFolder folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync("fileToSave" + fileext);
Stream data = Application.GetResourceStream(new Uri(file.Path, UriKind.Relative)).Stream;
string filename = System.IO.Path.GetFileName(file.Path);
ServerFunctions.UploadFile(filename,data);
Then I start the Upload
internal void UploadFile(string fileName,Stream data)
{
WebClient web = new WebClient();
if (!string.IsNullOrEmpty(dataRequestParam.AuthentificationLogin))
{
System.Net.NetworkCredential account = new NetworkCredential(dataRequestParam.AuthentificationLogin, dataRequestParam.AuthentificationPassword);
web.Credentials = account;
}
web.AllowReadStreamBuffering = true;
web.AllowWriteStreamBuffering = true;
web.OpenWriteCompleted += (sender, e) =>
{
PushData(data, e.Result);
e.Result.Close();
data.Close();
};
web.OpenWriteAsync(dataRequestParam.TargetUri,"POST");
}
private void PushData(Stream input, Stream output)
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, bytesRead);
}
}
The web server is supposed to send me as a response a xml with an error code or succes code inside.
None error is thrown but it doesnt work.And I don't understand why the e.result is a stream object. As I said the server should return a string...(xml file)
Could you bring me some explannations of what is happening in my code and if it will work with all types of files ?
Thanks
I think part of the problem here is that you're attempting to get this to behave like a streaming protocol when it seems you intend a request/response type architecture. For those purposes, you should consider working with a WebRequest object.
Bear with me as I fully qualify the namespace of the objects used inline, so it may get a little verbose, but I want you to know where to find these things.
internal async void UploadFile(string fileName, System.IO.Stream data)
{
// Specify URI, method, and credentials for the request
System.Net.WebRequest web = System.Net.HttpWebRequest.CreateHttp(dataRequestParam.TargetUri);
web.Method = "POST";
if (!string.IsNullOrEmpty(dataRequestParam.AuthenticationLogin))
{
web.Credentials = new System.Net.NetworkCredential(dataRequestParam.AuthenticationLogin, dataRequestParam.AuthenticationPassword);
}
// Create the request payload from the provided stream
System.IO.Stream requestStream =
await System.Threading.Tasks.Task<System.IO.Stream>.Factory.FromAsync(web.BeginGetRequestStream, web.EndGetRequestStream, null);
await data.CopyToAsync(requestStream);
// Get a response from the server
System.Net.WebResponse response =
await System.Threading.Tasks.Task<System.Net.WebResponse>.Factory.FromAsync(web.BeginGetResponse, web.EndGetResponse, null);
// Possibly parse the response with an XmlReader (example only)
System.Xml.XmlReader reader = System.Xml.XmlReader.Create(response.GetResponseStream());
string responseText = reader.ReadInnerXml(); // TODO: Real work here
}
The one oddity here is using the Task factory to create a task from the begin and end methods from getting both the request stream and the response. This makes it much simpler to consume these methods as you get a Task back which can be awaited for its return object, which you can then manipulate directly.
I'm not sure what form your response from the server takes on success versus failure, so I've simply shown how to create an XML reader to parse XML from the resulting stream. You can do whatever parsing is necessary yourself on these lines, but this should at least give you a look at what your server is returning in response.
The final code I use.
WebRequest web = HttpWebRequest.CreateHttp(dataRequestParam.TargetUri);
web.ContentType = dataRequestParam.ContentType;
web.Method = "POST";
web.ContentLength = data.Length;
if (!string.IsNullOrEmpty(dataRequestParam.AuthentificationLogin))
{
web.Credentials = new NetworkCredential(dataRequestParam.AuthentificationLogin, dataRequestParam.AuthentificationPassword);
}
using (var requestStream = await Task<Stream>.Factory.FromAsync(web.BeginGetRequestStream, web.EndGetRequestStream, web))
{
await data.CopyToAsync(requestStream);
}
WebResponse responseObject = await Task<WebResponse>.Factory.FromAsync(web.BeginGetResponse, web.EndGetResponse, web);
var responseStream = responseObject.GetResponseStream();
var sr = new StreamReader(responseStream);
string received = await sr.ReadToEndAsync();
return received;
}

Reading the content of HTTP Stream before the Content stream is Complete Windows Phone 8

I am trying to get a reference to a response stream before its complete in windows phone 8.
In other .Net platforms you can do
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(myUri);
WebResponse subscribeWebResponse = null;
Stream subscribeStream = null;
subscribeWebResponse = httpRequest.GetResponse();
subscribeStream = subscribeWebResponse.GetResponseStream();
For the purpose of creating Portable class libraries I've used the HttpClientLibrary from nuget.
This Adds ref to extensions assembly Microsoft.Net.Http
this allows me to return the async request at the time the headers have been read instead of waiting for the content transfer to be complete with
var clientResponse = await httpClient.SendAsync(requestmessage, HttpCompletionOption.ResponseHeadersRead);
The problem I'm having is that in windows phone 8 it doesn't work correctly, and still awaits the completion of the content stream to return.
Additionally
await httpWebRequest.BeginGetResponse(callback, request)
has the same behavior as these async methods are actually waiting for the completion of the web's response to continue execution.
So, is there any way to achieve the returning the response/stream at the point that i have received the response headers without Microsoft.Http.Net package?
Even if it has to be a Windows Phone 8 Platform Specific Solution?
Possibly an extension of HttpWebRequest?
From what I can tell, ResponseHeadersRead works on the WP8 emulator as it does on the desktop.
I installed the Win8 SDK. Created a windows phone app. I added this code to the MainPage ctor. This demonstrates a very rudimentary long polling example.
var client = new HttpClient();
var request = new HttpRequestMessage()
{
RequestUri = new Uri("http://oak:1001/longpolling")
};
client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, new CancellationToken())
.ContinueWith((t) =>
{
var response = t.Result;
response.Content.ReadAsStreamAsync()
.ContinueWith(s =>
{
var st = s.Result;
while (true)
{
var message= ReadNextMessage(st);
}
});
});
}
private static string ReadNextMessage(Stream stream)
{
int chr = 0;
string output = "";
while (chr != 10)
{
chr = stream.ReadByte();
output += Convert.ToChar(chr);
}
return output;
}
On my host dev machine I have a web api with a controller that looks like this...
public class LongPollingController : ApiController
{
public HttpResponseMessage Get()
{
Thread.Sleep(2000);
var content = new PushStreamContent( (s,c,t) =>
{
int i = 0;
while (true)
{
try
{
var message = String.Format("The current count is {0} " + Environment.NewLine, i++);
var buffer = Encoding.UTF8.GetBytes(message);
s.Write(buffer, 0, buffer.Length);
}
catch (IOException exception)
{
s.Close();
return;
}
Thread.Sleep(1000);
}
});
return new HttpResponseMessage(HttpStatusCode.OK)
{
RequestMessage = Request,
Content = content
};
}
}
So here's the deal. I would say that what you want to do is not possible, due to platform limitations... But SignalR has a WP client and is able to manage it. So it seems to me you have two options:
1) Dig into the SignalR source code to see how they do it (I'm on my phone right now so I can't provide a link).
UPDATE: Here is the link. They do some pretty neat tricks, like setting the Timeout to -1 for long-running clients. I think you should definitely use the techniques here.
OR
2) You can move whatever you're doing over to SignalR, which would gain the benefit of having a robust infrastructure and being cross-platform compatible.
HTH