I'm trying to stream radio in a Windows Phone 7 app and for this I'm using ManagedMediaHelpers. The HttpWebRequest to get the continuous stream works but doesn't call the callback Url because of the continuous stream.
How do I access the stream without the help of the callback Url? On other posts some said O need to use reflection but does someone knows hot to implement it? Here is my code:
req = (HttpWebRequest) WebRequest.Create(
"http://streamer-dtc-aa01.somafm.com:80/stream/1018");
// if this is false it will fire up the callback Url
// but the mediastreamsource will throw an exception
// saying the it needs to be true
req.AllowReadStreamBuffering = true;
IAsyncResult result = req.BeginGetResponse(RequestComplete,null);
private void RequestComplete(IAsyncResult r)
{
HttpWebResponse resp = req.EndGetResponse(r) as HttpWebResponse;
Stream str = resp.GetResponseStream();
mss = new Mp3MediaStreamSource(str, resp.ContentLength);
Deployment.Current.Dispatcher.BeginInvoke(() => {
this.me.Volume = 100;
this.me.SetSource(mss);
});
}
Had the same issue, so here is how I solved it:
Getting bytes from continuous streams on Windows Phone 7
It might also be a problem with your URL - make sure that if you run the request outside the application, you are getting the necessary amount of data.
Related
This question already has answers here:
How to perform a fast web request in C#
(4 answers)
Closed 7 years ago.
I've made an app that can access and control Onvif cameras which it does well enough. However this is my first time making any app that uses web requests like this (or at all) so I assume I'm probably using quite basic techniques.
The part of code I'm curious about is this:
Uri uri = new Uri(
String.Format("http://" + ipAddr + "/onvif/" + "{0}", Service));
WebRequest request = WebRequest.Create((uri));
request.Method = "POST";
byte[] b = Encoding.ASCII.GetBytes(PostData);
request.ContentLength = b.Length;
//request.Timeout = 1000;
Stream stream = request.GetRequestStream();
//Send Message
XmlDocument recData = new XmlDocument();
try
{
using (stream = request.GetRequestStream())
{
stream.Write(b, 0, b.Length);
}
//Store response
var response = (HttpWebResponse) request.GetResponse();
if (response.GetResponseStream() != null)
{
string responsestring = new
StreamReader(response.GetResponseStream())
.ReadToEnd();
recData.LoadXml(responsestring);
}
}
catch (SystemException e)
{
MessageBox.Show(e.Message);
}
return recData;
}
The code works fine, however using the writeline statements I've found that the first request takes about 400ms to complete whereas the subsequent ones only take between 10 - 20ms. Is there anything I can do to speed up the first request?
You're doing it just fine. The reason for the difference in time to complete may be due to HTTP Keep-Alive. By default, the same connection is reused for subsequent requests. So the first request has to establish the connection, which is probably why it takes longer. The rest of the requests use the same already-open connection.
Aside from potential network and server issues, the request itself matters. You can opt to reduce the size of the request or break it down and asynchronously load your files.
Web Servers out of the box will not take 400ms to complete a simple request.
I recently wrote an async HttpWebRequest client for our application and it works fine in .NET 3.5, but on Mono it fails to correctly write the data on to the request before sending it out.
I have confirmed the problem using wireshark to sniff the outgoing packets. The HTTP request is correctly set to POST with a JSON Content Type however the Content-Length and data are 0.
I currently get one exception:
The number of bytes to be written is greater than the specified
ContentLength.
I have tried to resolve this by manually setting the ContentLength of the WebRequest and changing the way I encode the data before giving it to the stream (I have tried both a Steam and StreamWriter).
I have also stepped through the code and debug logged the variables in the async method to ensure the data is really there. It just does not appear to be getting to the WebRequest object.
Here is the relevant code:
private void StartWebRequest(string payload) {
var httpWebRequest = (HttpWebRequest)WebRequest.Create(PortMapSleuthURL);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
httpWebRequest.Proxy = null; // Setting this to null will save some time.
// start an asynchronous request:
httpWebRequest.BeginGetRequestStream(GetRequestStreamCallback, new object[] {httpWebRequest, payload});
try {
// Send the request and response callback:
httpWebRequest.BeginGetResponse(FinishPortTestWebRequest, httpWebRequest);
} catch (Exception e) {
Console.WriteLine(e.Message);
PortTestException();
}
}
private void GetRequestStreamCallback(IAsyncResult asyncResult) {
try {
object[] args = (object[])asyncResult.AsyncState;
string payload = (string)args[1];
HttpWebRequest request = (HttpWebRequest)args[0];
//StreamWriter streamWriter = new StreamWriter(request.EndGetRequestStream(asyncResult), new UTF8Encoding(false));
StreamWriter streamWriter = new StreamWriter(request.EndGetRequestStream(asyncResult), Encoding.UTF8);
// Write to the request stream.
streamWriter.Write(payload);
streamWriter.Flush();
streamWriter.Close();
} catch (Exception e) {
Console.WriteLine(e.Message);
PortTestException();
}
}
I don't think you are supposed to call BeginGetResponse before EndGetRequestStream. That is, I would move that into the GetRequestStreamCallback. This is how the example on msdn works too.
I am new to C# so I was wondering if someone can help me out on this. I am trying to send HttpPost from Windows Phone 8 to the server. I found two examples that I would like to combine.
The first one is an example of sending Http Post (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream.aspx). The problem with this one is that it is not support by Windows Phone 8.
The second example is using the BeginGetResponse (http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.net.httpwebrequest(v=vs.105).aspx). This supports windows phone 8.
I need to convert the second example into a BeginGetRequestStream() like the first example. I will try to figure out this myself, but I am posting online if someone already knows how to do this. I am sure this will be helpful for other WP8 developers.
Update
I am now trying to get response from the server. I have started a new question. Please follow this link (Http Post Get Response Error for Windows Phone 8)
I am also currently working on a Windows Phone 8 project and here is how I am posting to a server. Windows Phone 8 sort of has limited access to the full .NET capabilities and most guide I read say you need to be using the async versions of all the functions.
// server to POST to
string url = "myserver.com/path/to/my/post";
// HTTP web request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "text/plain; charset=utf-8";
httpWebRequest.Method = "POST";
// Write the request Asynchronously
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream,
httpWebRequest.EndGetRequestStream, null))
{
//create some json string
string json = "{ \"my\" : \"json\" }";
// convert json to byte array
byte[] jsonAsBytes = Encoding.UTF8.GetBytes(json);
// Write the bytes to the stream
await stream.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
}
I propose a more generic asynchronous approach supporting success and error callbacks here:
//Our generic success callback accepts a stream - to read whatever got sent back from server
public delegate void RESTSuccessCallback(Stream stream);
//the generic fail callback accepts a string - possible dynamic /hardcoded error/exception message from client side
public delegate void RESTErrorCallback(String reason);
public void post(Uri uri, Dictionary<String, String> post_params, Dictionary<String, String> extra_headers, RESTSuccessCallback success_callback, RESTErrorCallback error_callback)
{
HttpWebRequest request = WebRequest.CreateHttp(uri);
//we could move the content-type into a function argument too.
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
//this might be helpful for APIs that require setting custom headers...
if (extra_headers != null)
foreach (String header in extra_headers.Keys)
try
{
request.Headers[header] = extra_headers[header];
}
catch (Exception) { }
//we first obtain an input stream to which to write the body of the HTTP POST
request.BeginGetRequestStream((IAsyncResult result) =>
{
HttpWebRequest preq = result.AsyncState as HttpWebRequest;
if (preq != null)
{
Stream postStream = preq.EndGetRequestStream(result);
//allow for dynamic spec of post body
StringBuilder postParamBuilder = new StringBuilder();
if (post_params != null)
foreach (String key in post_params.Keys)
postParamBuilder.Append(String.Format("{0}={1}&", key, post_params[key]));
Byte[] byteArray = Encoding.UTF8.GetBytes(postParamBuilder.ToString());
//guess one could just accept a byte[] [via function argument] for arbitrary data types - images, audio,...
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
//we can then finalize the request...
preq.BeginGetResponse((IAsyncResult final_result) =>
{
HttpWebRequest req = final_result.AsyncState as HttpWebRequest;
if (req != null)
{
try
{
//we call the success callback as long as we get a response stream
WebResponse response = req.EndGetResponse(final_result);
success_callback(response.GetResponseStream());
}
catch (WebException e)
{
//otherwise call the error/failure callback
error_callback(e.Message);
return;
}
}
}, preq);
}
}, request);
}
I am now just learning Windows Phone 7 development, I am using C#, as this is the language I am the most familiar with.
For now, I would like to create the following flow: user type something in a text field and press a button -> i show him a "Please wait" message box and send the text field text to a WebService (maybe over HTTPS), when the WebService response is received I will show him another screen, bases on the response data.
This WebService retrieves only JSON data, so I need to parse JSON data.
I think I am already able to send data and retrieve the response from the server, however, I dont know how to show this "loading" message box, hide it when dode, and start a new screen (blocking the access to this first one).
On button click:
HttpWebRequest wr = (HttpWebRequest)System.Net.WebRequest.Create("http://example.com/");
wr.Method = "POST";
wr.ContentType = "application/x-www-form-urlencoded";
wr.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), wr);
GetRequestStreamCallback method:
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest wr = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = wr.EndGetRequestStream(asynchronousResult);;
byte[] byteArray = Encoding.UTF8.GetBytes("key=" + someText.Text);
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
wr.BeginGetResponse(new AsyncCallback(GetResponseCallback), wr);
}
GetResponseCallback method:
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest wr = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)wr.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
MessageBox.Show(streamReader.ReadToEnd()); // ???
streamReader.Close();
streamResponse.Close();
response.Close();
}
catch (WebException e)
{
// Does nothing
}
}
Whatever method you use for progress indication, turn it on right before the call to the service, myProgressIndicator.Show = true; then in the callback and when done with any other processing, turn it off, myProgressIndicator.Show = false;. Don't forget to turn it off in the catch for exception handling as well.
Coding4Fun has a progress overlay.
I'm programming an application for Windows Phone 7. This application firstly sends, and then receives data from a server via HttpWebRequest. Most times it works fine, but sometimes, after receiving a portion of the data properly, I get a NullReferenceException in Stream.Read() function.
The communication starts when the user presses a button. Then I create the HttpWebRequest:
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(sUri);
request.Method = "POST";
request.BeginGetRequestStream(GetRequestStreamCallback, request);
The request callback method:
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
postStream = request.EndGetRequestStream(asynchronousResult);
this.bSyncOK = Send(); //This is my method to send data to the server
postStream.Close();
if (this.bSyncOK)
request.BeginGetResponse(GetResponseCallback, request);
else
manualEventWait.Set(); //This ManualResetEvent notify a thread the end of the communication, then a progressbar must be hidden
}
The response callback method:
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult) )
{
using (streamResponse = new StreamReader(response.GetResponseStream() ) )
{
this.bSyncOK = Recv(); //This is my generic method to receive the data
streamResponse.Close();
}
response.Close();
}
manualEventWait.Set(); //This ManualResetEvent notify a thread the end of the communication, then a progressbar must be hidden
}
And finally, this is the code where I get the exception reading the stream data:
int iBytesLeidos;
byte[] byteArrayUTF8 = new byte[8];
iBytesLeidos = streamResponse.BaseStream.Read(byteArrayUTF8, 0, 8); //NullReferenceException!!! -Server always send 8 bytes here-
When the application starts, I create a background thread that frequently sends info to the server. Background and Manual communications can run simultaneously. Could this be a problem?
Thanks.
If streamResponse is global variable, it can cause the problem in a case of an access from another thread. Pass your Stream to the Recv as a parameter
using (StreamReader streamResponse = new StreamReader(response.GetResponseStream() ) )
{
this.bSyncOK = Recv(streamResponse); //This is my generic method to receive the data
streamResponse.Close();
}
Where is your streamResponse declared in latter snippet? Is it the same object as in 3d snippet? Maybe you just use another variable, instead of actual stream.
in the second snippet, try to delete "postStream.Close();".