WebRequestExtensions.GetCurrentNetworkInterface throws InvalidOperationException - windows-phone-7

I want to get Network Interface on which HttpWebRequest was made
I found WebRequestExtensions.GetCurrentNetworkInterface function for this. HttpWebRequest also has GetCurrentNetworkInterface() method to perform the same.
This is my code:
HttpWebRequest httpWebRequest = HttpWebRequest.CreateHttp(new Uri(Url, UriKind.Absolute));
//this line throws InvalidOperationException
NetworkInterfaceInfo i = httpWebRequest.GetCurrentNetworkInterface();
I perform method call from UI thread. If I made call after BeginGetResponse exception tells "request was finished". What is workaround for this?
Exception info:
Message is InvalidOperationException
StackTrace:
at System.Net.Browser.ClientHttpWebRequest.GetConnectionDetails(IntPtr& Details, Int32& sizeofDetails)
at Microsoft.Phone.Net.NetworkInformation.WebRequestExtensions.GetCurrentNetworkInterface(WebRequest request)

HttpWebRequest httpWebRequest = HttpWebRequest.CreateHttp(new Uri(Url, UriKind.Absolute));
httpWebRequest.BeginGetResponse(result =>
{
// Handle response
}, null);
var info = WebRequestExtensions.GetCurrentNetworkInterface(httpWebRequest);
I had a similar problem recently and found you can't call GetCurrentNetworkInterface before BeginGetResponse (because the connection hasn't been made) but if you call it within the BeginGetResponse callback the request has already completed and you get the "Web request is already finished" error.
ADDED by question-starter:
Fully-worker code which allows to get NetworkInterfaceInfo of HttpWebRequest from background thread (used BackgroundWorker in this example to simulate this):
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s, 4) =>
{
HttpWebRequest httpWebRequest = HttpWebRequest.CreateHttp(new Uri("http://stackoverflow.com", UriKind.Absolute));
EventWaitHandle Wait = new AutoResetEvent(false);
httpWebRequest.BeginGetResponse(result =>
{
Wait.Set();
}, null);
Wait.WaitOne();
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var info = WebRequestExtensions.GetCurrentNetworkInterface(httpWebRequest);
MessageBox.Show(info.InterfaceType.ToString());
});
};
backgroundWorker.RunWorkerAsync();
ADDED AFTER FULL-DAY DEBUGGING:
I can't make it work 100% time, especially when loaded page is small. In this situation "request is finished" appears all the time. But with large loaded page it works even without EventWaitHandle

I beleive you might want to take a look at the NetworkInterface.NetworkInterfaceType Property. The documentation says that it returns the Interface type that is servicing current internet requests.
If this is not what you are looking for, you might also want to try the DeviceNetworkInformation class(I suspect you might have already looked at this option.). I think you could use the IsCellularDataEnabled and The IsWifiEnabled static properties.

Related

Web API Post hit before HttpWebRequest has finished streaming a large file

In our app (Silverlight 5 out-of-browser client hitting a WebApi server) we routinely use an HttpClient for posting/getting/deleting and so on all our entities between client and server. This all works fine most of the time, but recently we have run into an issue when uploading (posting) larger entities (> 30/35mb): we start the streaming process and BEFORE it is finished our Post method on the Web API is hit, receiving a null entity.
We can't understand what is going on, and suspect there must be some timing issue related since it all depends on the size of the upload.
To further explain, our client in summary is doing this:
HttpResponseMessage response = await _client.SendAsync(request);
string jsonResult = await response.Content.ReadAsStringAsync();
... where _client is our HttpClient and request our HttpRequestMessage. In case it is also relevant (I am trying not to flood the question with code :), the content in the request is created like this:
request.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
Well, when we debug this the Post method on our server is hit before the await _client.SendAsync(request) finishes, which sort of "explains" why it is receiving a null entity in such cases (larger entities), where when it works that await call is finished and THEN the Post is hit.
In case if sheds more light into it, due to certain limitations on the HttpClient (regarding access to AllowWriteStreamBuffering), we have also tested an equivalent scenario but using directly an HttpWebRequest... unfortunately, the behavior is exactly the same. This is the relevant extract:
httpRequest.BeginGetRequestStream(RequestStreamCallback, httpRequest);
(where httpRequest is our HttpWebRequest with AllowWriteStreamBuffering = false), and the callback to handle the request stream is as follows:
private void RequestStreamCallback(IAsyncResult ar)
{
var request = ar.AsyncState as System.Net.HttpWebRequest;
if (request != null)
{
var requestStream = request.EndGetRequestStream(ar);
var streamWriter = new StreamWriter(requestStream) {AutoFlush = true};
streamWriter.Write(_jsonContent);
streamWriter.Close();
requestStream.Close(); // Belt and suspenders... shouldn't be needed
// Make async call for response
request.BeginGetResponse(ResponseCallback, request);
}
}
Again, for larger entities when we debug the Post method on the Web API is hit (with a null parameter) BEFORE the streamWriter.Write finalizes and the streamWriter.Close is hit.
We've been reading all over the place and fighting with this for days on now. Any help will be greatly appreciated!
In case somebody runs into this, I finally figured out what was going on.
In essence, the model binding mechanism in the Web API Post method was throwing an exception when de-serializing the JSON, but the exception was somewhat "hidden"... at least if you did not know that much about the inner workings of the Web API, as was my case.
My Post method originally lacked this validation check:
var errors = "";
if (!ModelState.IsValid)
{
foreach (var prop in ModelState.Values)
{
foreach (var modelError in prop.Errors.Where(modelError => modelError != null))
{
if (modelError.Exception != null)
{
errors += "Exception message: " + modelError.Exception.Message + Environment.NewLine;
errors += "Exception strack trace: " + modelError.Exception.StackTrace + Environment.NewLine;
}
else
errors += modelError.ErrorMessage + Environment.NewLine;
errors += " --------------------- " + Environment.NewLine + Environment.NewLine;
}
}
return Request.CreateErrorResponse(HttpStatusCode.NoContent, errors);
}
This is a "sample" check, the main idea being verifying the validity of the ModelState... in our breaking scenarios is wasn't valid because the Web API hadn't been able to bind the entity, and the reason could be found within the Errors properties of the ModelState.Values. The Post was being hit ok, but with a null entity, as mentioned.
By the way, the problem was mainly caused by the fact that we weren't really streaming the content, but using a StringContent which was attempted to be de-serialized in full... but that is another story, we were mainly concerned here with not understanding what was breaking and where.
Hope this helps.

WP7 Get return value from Async HttpWebRequest

I have wrote this code:
private void button1_Click(object sender, RoutedEventArgs e)
{
HttpWebRequest request = SendRequests.CreateRequest(serverTextBox.Text);
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallback), request);
}
private void ReadWebRequestCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
try
{
HttpWebResponse myResponse = (HttpWebResponse)myRequest.EndGetResponse(callbackResult);
using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
{
string results = httpwebStreamReader.ReadToEnd();
loginValue = Parser.ParseLoginValue(results);
}
myResponse.Close();
}
catch (WebException we)
{
//
}
}
My problem at this point is that after the Click on the button I need the return value (here loginValue) of the BeginGetResponse to go on with the execution of the application.
I know that this is against the entire sense of asynchronous calls, but, there's a way to wait for the results before going on with the main thread?
Unfortunately, you have answered your own question. On Windows Phone, there is no way to do a synchronous web call.
But you don't really need to. If there is really nothing for your user to do while waiting for the response from the web, slap up a translucent overlay with a progress bar (or even better, use the global progress bar in the system try) and abide.
By contrast, if you were waiting for a synchronous call from the internet to return (which on a mobile device could take a long time), the UI would be locked and the user would think the application had hung (which, technically, is true).
Asynchronicity is your friend. Play nice with it.

ManualResetEvent with HttpWebRequest on WP7

To start off with, this might be tagged as a duplicate of the following thread:
Wait for HttpWebRequest.BeginGetResponse to finish in Windows Phone 7, however, the responses in that thread did not help me get over my problem.
To begin with, I am collecting user data on the UI Thread in order to process application registration, where I also have an instance of ManualResetEvent:
private static ManualResetEvent registrationEvent = new ManualResetEvent(false);
I have another thread which handles the registration process (and includes the HttpWebRequest.BeginGetResponse() and its corresponding callback method.)
Thread t = new Thread(() => RegistrationHandler.sendRegistrationData(url));
t.Start();
Right after this call, I block the current (UI) thread with a call to
registrationEvent.WaitOne();
//Process the response, update some UI elements and navigate to a different page.
httpSessionCompleted(response);
Once the thread handling the registration process starts, I am instantiating HttpWebRequest and invoking the BeginGetResponse() method on it.
try
{
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.Method = "POST";
request.ContentType = mimeType;
request.BeginGetResponse(new AsyncCallback(GetRequestCallback), request);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in sendData(): {0}", ex.Message);
}
Now the issue is that the callback method (code below) is never invoked, and the application just freezes. There also doesn't seem to be any exception(s) thrown either.
try
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
if (request != null)
{
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
String result = reader.ReadToEnd();
Globals.HostResponse = result;
//Signalling the calling thread to continue execution
RegistrationPage.RegistrationEvent.Set();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in GetRequestCallback(): {0}", ex.Message);
}
I ideally want my application to continue from httpSessionCompleted() after the callback method finishes execution. Can someone please help me with some guidance/suggestions?
Sorry for being verbose. Thanks!
You should not block UI thread, use callback pattern instead. Look at this: Windows Phone 7 - wait for Webclient to complete . Hope this helps

Accessing a website using C#

I'm trying to make an App for windows phone 7. This app will basiclly retrive information from a website that we use at work as our working schedule then rearrange the retrived info into a metro style UI. To be honest i don't know where to start ie. how to retrive the info. Should i use webclient class? httpwebrequest class? or something else?
All idea are appriciated
Here is a:-
Update:-
Okay either im totally stupid or there is something wrong with the code i'm writing, that i can't figure it out. I was using the same code that you wrote BUT i still get an error that a definition for Proxy is not in the System.Net.WebRequest :( This is my code (the working version):-
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
string url = "https://medinet.se/*****/schema/ibsef";
WebRequest request = WebRequest.Create(url);
request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallBack), request);
}
private void ReadWebRequestCallBack(IAsyncResult callbackResult)
{
try
{
WebRequest myRequest = (WebRequest)callbackResult.AsyncState;
WebResponse myResponse = (WebResponse)myRequest.EndGetResponse(callbackResult);
using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
{
string results = httpwebStreamReader.ReadToEnd();
Dispatcher.BeginInvoke(() => parsertextBlock.Text = results);
}
myResponse.Close();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
Dispatcher.BeginInvoke(() => parsertextBlock.Text = ex.ToString());
}
}
But if i add request.Proxy=null!! i get an error, that there is no definition for Proxy in (System.Net.WebRequest). And to be honest i start getting mad of this.
Yours
/Omar
The process is called ScreenScrape and i recommend you to use Html Agility Pack http://htmlagilitypack.codeplex.com/ . Make a web service that retrieves the information from your website and rearranges to appropriate format. Use your web service by a phone and display your data.
Use WebRequest ( http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx) and WebResponse ( http://msdn.microsoft.com/en-us/library/system.net.webresponse(v=vs.100).aspx) .
TIP: Set the WebRequest.Proxy property ( http://msdn.microsoft.com/en-us/library/system.net.webrequest.proxy.aspx) to null, as i find it will be much faster.
UPDATE: More info on WebRequest Proxy property
Set Proxy = null on the WebRequest object to avoid an initial delay (that way the request won't start auto detecting proxies, which i find it's faster).
WebRequest req = WebRequest.Create("yourURL");
req.Proxy = null;
It's in the System.Net namespace so put an using statement using System.Net; or
System.Net.WebRequest req = WebRequest.Create("yourURL");
req.Proxy = null;
Regards.

SmtpClient.SendAsync blocking my ASP.NET MVC Request

I have a Action that sends a simple email:
[HttpPost, ActionName("Index")]
public ActionResult IndexPost(ContactForm contactForm)
{
if (ModelState.IsValid)
{
new EmailService().SendAsync(contactForm.Email, contactForm.Name, contactForm.Subject, contactForm.Body, true);
return RedirectToAction(MVC.Contact.Success());
}
return View(contactForm);
}
And a email service:
public void SendAsync(string fromEmail, string fromName, string subject, string body, bool isBodyHtml)
{
MailMessage mailMessage....
....
SmtpClient client = new SmtpClient(settingRepository.SmtpAddress, settingRepository.SmtpPort);
client.EnableSsl = settingRepository.SmtpSsl;
client.Credentials = new NetworkCredential(settingRepository.SmtpUserName, settingRepository.SmtpPassword);
client.SendCompleted += client_SendCompleted;
client.SendAsync(mailMessage, Tuple.Create(client, mailMessage));
}
private void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
Tuple<SmtpClient, MailMessage> data = (Tuple<SmtpClient, MailMessage>)e.UserState;
data.Item1.Dispose();
data.Item2.Dispose();
if (e.Error != null)
{
}
}
When I send a email, I am using Async method, then my method SendAsync return immediately, then RedirectToAction is called. But the response(in this case a redirect) isnĀ“t sent by ASP.NET until client_SendCompleted is completed.
Here's what I'm trying to understand:
When watching the execution in Visual Studio debugger, the SendAsync returns immediately (and RedirectToAction is called), but nothing happens in the browser until email is sent?
If i put a breakpoint inside client_SendCompleted, the client stay at loading.... until I hit F5 at debugger.
This is by design. ASP.NET will automatically wait for any outstanding async work to finish before finishing the request if the async work was kicked off in a way that calls into the underlying SynchronizationContext. This is to ensure that if your async operation tries to interact with the HttpContext, HttpResponse, etc. it will still be around.
If you want to do true fire & forget, you need to wrap your call in ThreadPool.QueueUserWorkItem. This will force it to run on a new thread pool thread without going through the SynchronizationContext, so the request will then happily return.
Note however, that if for any reason the app domain were to go down while your send was still in progress (e.g. if you changed the web.config file, dropped a new file into bin, the app pool recycled, etc.) your async send would be abruptly interrupted. If you care about that, take a look at Phil Haacks WebBackgrounder for ASP.NET, which let's you queue and run background work (like sending an email) in such a way that will ensure it gracefully finishes in the case the app domain shuts down.
This is an interesting one. I've reproduced the unexpected behaviour, but I can't explain it. I'll keep digging.
Anyway the solution seems to be to queue a background thread, which kind of defeats the purpose in using SendAsync. You end up with this:
MailMessage mailMessage = new MailMessage(...);
SmtpClient client = new SmtpClient(...);
client.SendCompleted += (s, e) =>
{
client.Dispose();
mailMessage.Dispose();
};
ThreadPool.QueueUserWorkItem(o =>
client.SendAsync(mailMessage, Tuple.Create(client, mailMessage)));
Which may as well become:
ThreadPool.QueueUserWorkItem(o => {
using (SmtpClient client = new SmtpClient(...))
{
using (MailMessage mailMessage = new MailMessage(...))
{
client.Send(mailMessage, Tuple.Create(client, mailMessage));
}
}
});
With .Net 4.5.2, you can do this with ActionMailer.Net:
var mailer = new MailController();
var msg = mailer.SomeMailAction(recipient);
var tcs = new TaskCompletionSource<MailMessage>();
mailer.OnMailSentCallback = tcs.SetResult;
HostingEnvironment.QueueBackgroundWorkItem(async ct =>
{
msg.DeliverAsync();
await tcs.Task;
Trace.TraceInformation("Mail sent to " + recipient);
});
Please read this first: http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
I sent the bug to Microsoft Connect https://connect.microsoft.com/VisualStudio/feedback/details/688210/smtpclient-sendasync-blocking-my-asp-net-mvc-request

Resources