WP8 Fast App Resume with Asynchronous methods - c#

In my windows phone 8 app i am using asynchronous methods to retrieve data from server.
After implementing Fast App Resume functionality another problem rose for me. The asynchronous method that retrieves data from server throws the exception of type System.Net.WebException when it resumes.
The steps to reproduce the problem is you just hit the start button when the app is loading data by asynchronous method.
For example i have a page that loads notification of user. I called the async void GetNotifications() method that further calls below method to retrieve response string.
public async Task<string> Get(string URL)
{
var request = WebRequest.Create(new Uri(URL)) as HttpWebRequest;
if (APIHelper.APIHandshake != null)
request.Headers["Cookie"] = "ii=" + APIHelper.APIHandshake.Sid + ";";
return await httpRequest(request);
}
the implementation of httprequest method is given below.
private async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory
.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
//cookieJar = request.CookieContainer;
//responseCookies = response.Cookies;
received = await sr.ReadToEndAsync();
}
}
}
return received.Replace("[{}]", "[]")
.Replace("[{},{}]", "[]")
.Replace("\"subcat_id\":\"\"", "\"subcat_id\":\"0\"");
}
The user just click the menu that opens the notification page and then press the start button of phone instantly to deactivate the app. When user will click on application tile from start menu the exception will be thrown.
Any solution? will deactivating idle mode detection work?

It would probably not be the best solution but It is possible to not cancel the async request by adding this line of code in the InitalizePhoneApplication() method on your app.xaml.cs page.
PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled;
Read more on this property here
Test it, it should fix the issue but I'm not pretending that's the best thing to do....

Related

Forward multipart/x-mixed-replace live stream ASP.NET Core

I've an ASP.NET Core server that, upon client request, start fetching a stream from an AXIS camera and returns it to the client for displaying. If the http request to server is made directly by the browser by means of img src attribute, it works fine. But if I use HttpClient (which I need to do since I need CancellationToken), the httpClient.GetStreamAsync instruction get stuck and I cannot parse the returned data.
Server side Controller (take from here):
[ApiController]
[Route("[controller]")]
public class CameraSystemController : ControllerBase
{
private string _contentTypeStreaming = "multipart/x-mixed-replace;boundary=myboundary";
private HttpClient _httpClient = new HttpClient(new HttpClientHandler { Credentials = ...});
[HttpGet("getStream")]
public async Task<IActionResult> GetStream(CancellationToken token)
{
Stream stream = await _httpClient.GetStreamAsync("http://.../axis-cgi/mjpg/video.cgi?resolution=800x600&compression=50", token);
if (stream != null) {
FileStreamResult result = new FileStreamResult(stream, _contentTypeStreaming) {
EnableRangeProcessing = true
};
return result;
} else {
return new StatusCodeResult((int)HttpStatusCode.ServiceUnavailable);
}
}
}
Now, as I said, as long as I make the browser perform the http request by means of
// LiveCamera.razor
<img src="CameraSystem/getStream" onerror="#OnImgLoadingError" alt="">
Data acquired in live mode by the camera is correctly displayed in browser.
If instead I make the request in the client this way:
//LiveCamera.razor.cs
[Inject] public HttpClient Http { get; private set; }
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private async void StartStreamingRequest(object sender, ElapsedEventArgs e) {
Console.WriteLine("I'm about to request live stream");
Stream responseStream = await Http.GetStreamAsync("CameraSystem/getStream", _cancellationTokenSource.Token);
Console.WriteLine("Header found!");
string boundary = "myboundary";
for (MultipartReader streamReader = new MultipartReader(boundary, responseStream); ;) {
MultipartSection nextFrame = await streamReader.ReadNextSectionAsync(_cancellationTokenSource.Token);
DisplayOneFrameCallback(nextFrame.Body);
}
}
private void DisplayOneFrameCallback(Stream body)
{
StreamReader reader = new StreamReader(body);
string frameData = reader.ReadToEnd();
_imgSrc = "data:image/jpeg;base64," + frameData;
StateHasChanged();
}
In this seconds case the request is performed correctly (server-side I can see the code executed and from task manager I can see the bandwidth usage increasing) but the client got stuck on await instruction, and subsequent code is never executed. Now, in Microsoft documentation under GetStreamAsync it is possible to read
This operation will not block. The returned Task object will complete after the response headers are read. This method does not read nor buffer the response body.
so I would expect it not to block. Thus I suppose there could be a problem in the header I'm producing server-side, even though browser request works just fine.
Just out of curiosity, I've captured with Wireshark the data between the camera and the server. The header and the initial part of the body are like this:
..-...HTTP/1.0 200 OK..Cache-Control: no-cache..Pragma: no-cache..Expires: Thu, 01 Dec 1994 16:00:00 GMT..Connection: close..Content-Type: multipart/x-mixed-replace;boundary=myboundary....--myboundary..Content-Type: image/jpeg..Content-Length: 30146......
I've double-checked with browser developer tools and I can confirm that sending the request from browser or from httpClient yield the same exact request. Furthermore right-clicking on the request url and issueing "open in new tab" opens a tab where I can see the camera live stream in both cases.
Could you please help me in this?

How to handle continous GET requests?

I am working on a little Windows Form Application, that shows me the streams of several IP Cameras (from different companies) in my Network and also allows me to move the Cameras (left,right,up,down,zoom). This is realised with AFORGE.net MJPEG Streams and the camera movements through firing get requests.
Problem: I have one camera that doesn't move in steps (after each click on 'up' for example) but it moves continuously. It only stops when I send another request with the parameter 'stop'.
GET Request to Move Right:
http://192.XXX.XX.XXX:XXXX/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=right&-speed=63
GET Request to Stop the movement:
http://192.XXX.XX.XXX:XXXX/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&- act=stop&-speed=63
Function I use for the other Cameras:
private void move_right()
{
string url = 'someURL';
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.GetResponse();
request.Abort();
}
I would like the camera to move right stepwise after clicking a button, but when firing the request to move right, my program just gets stuck.
Use the HttpClient object and create an asynchronous request, try something like (untested):
private async Task move_right()
{
var url = 'someURL';
var client = new HttpClient();
var request = new HttpRequestMessage()
{
RequestUri = new Uri(url),
Method = HttpMethod.Get,
};
var response = await client.SendAsync(request);
//Do something with your response
}
private async Task executeWebRequests()
{
//Usage - Await for result
await move_right();
//Execute asynchronously
move_right(); //Will create a new task and run asynchronously in the BG
move_right(); //Will create a new task and run asynchronously in the BG
move_right(); //Will create a new task and run asynchronously in the BG
move_right(); //Will create a new task and run asynchronously in the BG
}
I have a camera using the same url.
This thread is a few years old, but for anyone else interested, use step=1 to move stepwise.

How to hit a rest api url from asp.net MVC 5

Actually I want to hit a url(if i hit same url from browser, SMS is coming to my number but not from the code) to send sms on mobile. the same code is working for me in C# windows app but in mvc it's giving error as excption[An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%# Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.]
Sample code in MVC-5
void sendSMS(string name, string mobile)
{
try
{
string mobNumber = mobile;
string message = "Hello "+name+" your request submitted successfully.";
string apiToken = "xxxxxxxxxxx";
string smsSender = "xxxxxx";
string apiKey = "test#gmail.com";
string url = "http://somewebsite.com/Restapis/send_sms?api_key=" + apiKey + "&api_token=" + apiToken + "&sender=" + smsSender + "&receiver=" + mobNumber + "&msgtype=1&sms=" + message + "";
GetRequest(url, mobNumber);
}
catch(Exception ex){ }
}
public async static void GetRequest(string url, string mob)
{
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url))
{
using (HttpContent content = response.Content)
{
HttpContentHeaders headers = content.Headers;
if (response.ReasonPhrase == "OK") { }
}
}
}
}
Above same code is working in windows App but not in ASP.NET MVC.
Please anyone provide a hint or solution. Thanks in advance.
This is a known issue in ASP.NET.
Replace this line:
using (HttpResponseMessage response = await client.GetAsync(url))
With this:
using (HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false))
You need to use ConfigureAwait or the threads will block.
Check this post for more details.
So, according to it, ASP.NET has a specialized sync context, that only
one thread can have. And if you don’t use .ConfigureAwait(false), it
tries to restore old context, which belongs to the main thread that is
blocked by .Result, hence deadlock.

Streaming Content constantly updating 8x8 streaming service

I have tried to create a simple console application.
We have a call system from 8x8 that provide a web streaming API but their documentation is very limited and nothing in C#.
The api service streams call statuses in near real time and I would like to get that 'stream' and be able to read and process it in realtime if possible. The response or Content Type is 'text/html'. But the actual body of the response can be declared as json - sample below:
{"Interaction":{"attachedData":{"attachedDatum":[{"attachedDataKey":"#pri","attachedDataValue":100},{"attachedDataKey":"callingName","attachedDataValue":999999999999},{"attachedDataKey":"cha","attachedDataValue":99999999999},{"attachedDataKey":"cnt","attachedDataValue":0},{"attachedDataKey":"con","attachedDataValue":0},{"attachedDataKey":"med","attachedDataValue":"T"},{"attachedDataKey":"pho","attachedDataValue":9999999999},{"attachedDataKey":"phoneNum","attachedDataValue":9999999999},{"attachedDataKey":"tok","attachedDataValue":999999999}]},"event":"InteractionCreated","inboundChannelid":9999999999,"interactionEventTS":9999999,"interactionGUID":"int-15b875d0da2-DJOJkDhDsrh3AIaFP8VkICv9t-phone-01-testist","resourceType":0}}
I have seen several posts concerning httpClient and the GetAsync methods but none of these appear to work as they appear to be for calls when a response is made, not something that constantly has a response.
Using fiddler for the call it does not appear to close so the stream is constantly running, so fiddler does not display any data until a separate user or instance connects.
When I use a browser the content is 'streamed' to the page and updates automatically and shows all the content (as above).
The api contains authentication so when another client connects and retrieves data the connected client closes and finally I am able to see the data that was gathering.
This is the code so and does return the big stream when another client connects but ideally I want a real time response and appears to just get stuck in the GETASYNC method:
var response = await client.GetAsync(address, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = await responseContent.ReadAsStringAsync();
Console.WriteLine(responseString);
}
Hopefully that's enough information for one of you clever people to help me in my predicament.
I was also having an issue consuming their streaming API and the examples I found that worked with the Twitter and CouchBase streaming API's did not work with 8x8. Both Twitter and CouchBase send line terminators in their pushes so the solution relied on ReadLine to pull in the feed. Since 8x8 does not send terminators you'll need to use ReadBlock or better ReadBlockAsync.
The following code shows how to connect using credentials and consume their feed:
private static async Task StreamAsync(string url, string username, string password)
{
var handler = new HttpClientHandler()
{
Credentials = new NetworkCredential {UserName = username, Password = password},
PreAuthenticate = true
};
// Client can also be singleton
using (var client = new HttpClient(handler))
{
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Connection.Add("keep-alive");
using (var response = await client.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead))
{
using (var body = await response.Content.ReadAsStreamAsync())
{
using (var reader = new StreamReader(body))
{
while (!reader.EndOfStream)
{
var buffer = new char[1024];
await reader.ReadBlockAsync(buffer, 0, buffer.Length);
Console.WriteLine(new string(buffer));
}
}
}
}
}
}

Windows phone 8 dev: HttpWebRequest.BeginGetResponse callback never called

I'm starting windows phone 8 development on my Windows 8 machine and test on the emulator that comes with visual studio 2012. I have a main page with one button on it. Upon pressing the button, it makes a http request.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
string uriString = "http://209.143.33.109/mjpg/video.mjpg?camera=1";
var uri = new Uri(uriString);
var httpWebRequest = HttpWebRequest.Create(uri);
httpWebRequest.BeginGetResponse(new AsyncCallback(OnGettingResponse), httpWebRequest);
}
private void OnGettingResponse(IAsyncResult ar)
{
var req = ar.AsyncState as HttpWebRequest;
var response = (HttpWebResponse)req.EndGetResponse(ar);
var responseStream = response.GetResponseStream();
}
I set a breakpoint on OnGettingResponse. But when I press the button, the breakpoint is never hit.
Am I missing anything obvious here?
I was facing the same issue that my callback was not being called even after waiting too long.
I found this stackoverflow answer https://stackoverflow.com/a/15041383 and modified my code accordingly. The actual problem in that question was that asker wants to have some timeout functionality in the HttpWebRequest under Windows Phone 8. Having timer was irrelevant for me, so I just took the following part of code:
public async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
return received;
}
and modified my call to this method as:
var response = await httpRequest(request);
This is now working fine for me.
I also double checked that ID_CAP_NETWORKING is check in WMAppManifest.xml and internet is working on my emulator.

Categories

Resources