How to cancel HttpClient GET Web request - windows-8

Is it possible to cancel HttpClient GET web request in Windows 8. I am looking for a solution to cancel my web request if the user press back key from the page. In my app i am using a static class for creating web request.
Alos i am using MVVM Light, and static viewmodels inside the app.
In the current situation, even if the user press the back button,
the vm stay alive and the call back reaches and executes in the VM.
So i am looking for a solution to cancel the request on back press.

Try this
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
await HttpGetRequest();
}
public CancellationTokenSource cts = new CancellationTokenSource();
private async Task HttpGetRequest()
{
try
{
DateTime now = DateTime.Now;
var httpClient = new HttpClient();
var message = new HttpRequestMessage(HttpMethod.Get, "https://itunes.apple.com/us/rss/toppaidapplications/limit=400/genre=6000/json");
var response = await httpClient.SendAsync(message, cts.Token);
System.Diagnostics.Debug.WriteLine("HTTP Get request completed. Time taken : " + (DateTime.Now - now).TotalSeconds + " seconds.");
}
catch (TaskCanceledException)
{
System.Diagnostics.Debug.WriteLine("HTTP Get request canceled.");
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
cts.Cancel();
}

The answer by #Farhan Ghumra is correct. Since we have moved to .Net 6 just like to add the following to the answer.
After you’re completely done with the CancellationTokenSource, dispose it directly E.g use cts.Dispose() (because you’ll most likely be using this with UI code and needing to share it with click event handling code, which means you wouldn’t be able to dispose of it with a using block)
More information can be found here.

Related

Issue of multiple SQL notifications in ASP.Net web application on page refresh

I am facing an issue while using SQL Server Notifications. I am developing a web application in ASP.net where one of the page needs to be notified about new entries in one of the tables in a SQL Server database. I am using SQL Server Notification services along with Signal R to achieve this functionality.All seems to work fine with my web page getting updates about new data entries.
The problem arises when the page using notification is refreshed. I find the no of notification for single entry in database go up by the number of refreshes. So if I refresh the page thrice, I get 3 notifications for one entry. I am bit concerned if this would be a burden on server when the no of connected users increases. Also if there is an error while processing the request to update the page with new entry, the user gets multiple error messages with same text. I tried debugging my code and found out that the on change event of SqlDependency object used is fired multiple time with different IDs every time. Below is brief overview of what my code is doing to use notifications -
I am using SQL Server 2012 and enable_broker is set for the database.
In global.asax, I am using application_start and application_stop events to start and stop SqlDependency.
In page code, I am setting a new SqlDependency object on page load using a command object to monitor the exact data field of the table.
When onchange of SqlDependency object fires, I am notifying the UI using Signal R hub class. Then I remove the OnChange handler of the SqlDependency object, call for SqlDependency.Stop(connectionstring), set SqlDependency object to nothing, call for SqlDependency.Start(connectionstring) and finally set up the SqlDependency object again using the command object for updated data. This whole set to nothing-stop-start-reset object is to continue monitoring the data for changes.
The above steps work fine but when I refresh the page, those are repeated for the number of refreshes. I tried a lot of things by changing code and debugging but nothing seems to resolve the issue. Now I am wondering if it is some setting somewhere that I missed.
Please help me resolve this issue. Also let me know if any other information such as environment, coding details etc are required.
Regards,
Tanmay
This is probably caused by connection pooling. It reurns a notification for each connection open in the pool. You can cancel the pooling for this specific service by changing the Connection String property:
Pooling = False;
i have resolved the following problem by using the below code, its works me.
SingletonDbConnect.cs
public class SingletonDbConnect
{
private static SingletonDbConnect dbInstance;
private static string connString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
private readonly SqlConnection conn = new SqlConnection(connString);
private SingletonDbConnect()
{
}
public static SingletonDbConnect getDbInstance()
{
if (dbInstance == null)
{
dbInstance = new SingletonDbConnect();
}
return dbInstance;
}
public SqlConnection getDbConnection()
{
try
{
conn.Close();
conn.Open();
}
catch (SqlException e)
{
}
finally
{
}
return conn;
}
}
SqlDependencyEvent.cs
public class SqlDependencyEvent
{
internal static int PageLoadCounter = 0;
public void getEmailMessagesByEmailId(Guid emailid)
{
SingletonDbConnect conn = SingletonDbConnect.getDbInstance();
using (MembersController.command = new SqlCommand(SQL.emailmessagesbyaccount_sql(), conn.getDbConnection()))
{
MembersController.command.Notification = null;
if (MembersController.dependency == null)
{
MembersController.dependency = new SqlDependency(MembersController.command);
MembersController.dependency.OnChange += new OnChangeEventHandler(emailMessages_OnChange);
}
var reader = MembersController.command.ExecuteReader();
}
PageLoadCounter++;
}
private void emailMessages_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
if (MembersController.dependency != null)
{
MembersController.dependency.OnChange -= emailMessages_OnChange;
}
NotificationHub.EmailUpdateRecords();
SingletonDbConnect conn = SingletonDbConnect.getDbInstance();
using (MembersController.command = new SqlCommand(SQL.emailmessagesbyaccount_sql(), conn.getDbConnection()))
{
MembersController.command.Parameters.Add(new SqlParameter("#emailaccountid", defaultemailid));
MembersController.command.Notification = null;
MembersController.dependency = new SqlDependency(MembersController.command);
MembersController.dependency.OnChange += new OnChangeEventHandler(emailMessages_OnChange);
var reader = MembersController.command.ExecuteReader();
}
PageLoadCounter++;
}
}
}
MembersController.cs
public class MembersController : Controller
{
SingletonDbConnect conn = SingletonDbConnect.getDbInstance();
internal static SqlCommand command = null;
internal static SqlDependency dependency = null;
//
// GET: /Members/
public ActionResult Index()
{
SqlDependency.Stop(conn.getDbConnection().ConnectionString);
SqlDependency.Start(conn.getDbConnection().ConnectionString);
return View();
}
}
its resolved my problem and its working me, even we refresh page more than 1, but SqlDependency will call only once.
i used one of the MembersController for SqlDependency start and stop, its your own logic, you can use the same code in Global.ascx instead of MembersController.cs
i hope it will help you and resolve issue. ask me if you have still any problem thanks.

wcf callback + save session not operationcontext

I'm new to stackoverflow however I use it everyday. Today I need you because I dont get this info anywhere.
My question is:
I want to make a service with callback to clients but I dont want to callback in the function they call in the service. (something like subscriber/publisher)
I want to save the callback instance.
Then I want a service calling a function in my service that will trigger the callbacks(like this: callbacks.PrintMessage("Message"));)
Saving the callback instance in a static list in a static class.
When calling the callback.function() Im getting this error: "you are using Disposed object"
because Im getting the instance with this: OperationContext.Current.GetCallbackChannel<"callback interface">
What can I do to save that callback instances?
Thanks a lot.
Pedro
CODE:
//FUNCTION IN MY SERVICE
public void Subscribe()
{
var callback = OperationContext.Current.GetCallbackChannel<IMonitoringWebServiceCallback>();
callbacks.Add(callback);
callback = OperationContext.Current.GetCallbackChannel<IMonitoringWebServiceCallback>();
AlarmCallbackSingleton.Instance.AddCallback(callback);
//callback.PrintString("String"); //HERE IT WORKS! BUT I DONT WANT CALL HERE!
alarmInfoHandler = new AlarmInfoEventHandler(AlarmInfoHandler);
NewAlarmInfo += alarmInfoHandler;
}
//FUNCTION IN THE SAME SERVICE CALLED BY OTHER CLIENT
public void PublishAlarm(string alarm)
{
AlarmInfoEventArgs e = new AlarmInfoEventArgs();
e.Alarm = alarm;
NewAlarmInfo(this, e);
}
public void AlarmInfoHandler(object sender, AlarmInfoEventArgs e)
{
List<IMonitoringWebServiceCallback> callbacks = AlarmCallbackSingleton.Instance.GetCallbacks();
//EVERYONE THAT SUBSCRIBED SHOULD EXECUTE THIS (HERE I GET THE DISPOSED ERROR)
callbacks.ForEach(x => x.ShowString("String!"));
}
Ok. I got it! The answer to this question is as simple as this:
When you subscribe to the service you need to save somewhere(List etc..) the OperationContext and not the callback object.
Then when the PublishAlarm is called by another client the event is triggered and you need to get OperationContext of all clients that subscribe.
I saved that objetcs in a static List(singleton class) just for the example.
Then:
public void AlarmInfoHandler(object sender, AlarmInfoEventArgs e)
{
var operation = AlarmCallbackSingleton.Instance.operationContext
var callback = operation.GetCallbackChannel<IMonitoringWebServiceCallback>();
callback.ShowAlarm(); //function you want to call
}
Hope this can help!

WCF & Silverlight >> pollingDuplexHttpBinding >> Calling web services from silverlight as the browser is closed

I have WCF server and Silverlight client using pollingDuplexHttpBinding binding .
I wanna close the connection and call the EndSession operation method , which clears the user from
active users list, and close the session ( IsTerminating = true )
[OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]
void EndSession();
according to this , you can't call on wcf operation on Application_Exit event , it also gives a
solution which seems "2 much noisy" to me ,
What's my options here? Is this the only way?
1) Using the link solution?
2) Server running a method every X seconds to check duplex object state is alive?
(((ICommunicationObject)clientContract.Value).State != CommunicationState.Opened
3) Other ?! Easy built-in solution ? Why Silverlight is HELL ?!
This is the solution which I just tried out and which works. Its core was posted in the comments in the link from your question! :)
Silverlight App.Exit event:
private void Application_Exit(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(App.SessionId))
return;
var page = HtmlPage.Document.DocumentUri;
UriBuilder builder = new UriBuilder();
builder.Scheme = page.Scheme;
builder.Host = page.Host;
builder.Port = page.Port;
builder.Path = page.LocalPath;
string request = builder.Uri.ToString();
request += "?closing=" + App.SessionId;
System.Windows.Browser.ScriptObject obj = System.Windows.Browser.HtmlPage.Window.CreateInstance("XMLHttpRequest");
obj.Invoke("open", "POST", request, false);
obj.Invoke("setRequestHeader", "Content-Type", "application/x-www-form-urlencoded");
obj.Invoke("send", "");
}
The above code sends a request to the page that hosts the Silverlight object, which is an ASPX page and has the following code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(this.Request.QueryString["closing"]))
chatSvc.Quit(this.Request.QueryString["closing"]);
}
chatSvc should, obviously, be a reference to your service and Quit whatever method you want to call whenever a client closes. You can pass required parameters via query string.
It's not pretty, I admit, but it does work.
EDIT:
The reason I'm not using DocumentUri directly, is because I'm using the navigation framework for my Silverlight application.

Trouble Attaching File Programmatically to Email in Windows Metro App C#/XAML using Share Charm

I'm simply trying to attach a file named Document.pdf in the DocumentsLibrary to an email using the Share Charm. My code below works perfectly on the Local Machine:
private async void OnDataRequestedFiles(DataTransferManager sender, DataRequestedEventArgs e)
{
List<IStorageItem> shares = new List<IStorageItem>();
StorageFile filetoShare = await Windows.Storage.KnownFolders.DocumentsLibrary.GetFileAsync("Document.pdf");
if (filetoShare != null)
{
shares.Add(filetoShare);
filetoShare = null;
}
if (shares != null)
{
DataPackage requestData = e.Request.Data;
requestData.Properties.Title = "Title";
requestData.Properties.Description = "Description"; // The description is optional.
requestData.SetStorageItems(shares);
shares = null;
}
else
{
e.Request.FailWithDisplayText("File not Found.");
}
}
But when I run the exact same code on a Windows Surface Tablet, I get the dreaded "There's nothing to share right now." on the right in the Charms flyout area.
Here's a little more background to help:
I'm not looking to use a File Picker...I know the exact file I'm looking for
I've enabled the Documents Library Capability in the manifest
I've added a File Type Association for pdf in the manifest
and yes, the file does exist and is in the Documents Library
an email account is properly setup in the Mail App on the surface
I can successfully send text emails from the Tablet...just not emails with attachments
Like I said, this works on my Win 8 Development Machine as expected...just not on the Surface. I'm wondering if the Surface has different file or folder permissions?
Thanks for the help...this is driving me CRAZY
I finally figured it out - the problem was that my Event Handler was async (so that I could use await to set the StorageFile variable).
I solved it by setting the StorageFile variable earlier in my code so that it was already available when the Event Handler was called.
I still have no idea why it worked on my development machine, but no on the WinRT surface...
The handler can be an async method. In this case, it is critical to use DataTransferManager. Please refer to the MSDN page specifically for this scenario. For your convenience, the code from the page is copied to here:
private void RegisterForShare()
{
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager,
DataRequestedEventArgs>(this.ShareStorageItemsHandler);
}
private async void ShareStorageItemsHandler(DataTransferManager sender,
DataRequestedEventArgs e)
{
DataRequest request = e.Request;
request.Data.Properties.Title = "Share StorageItems Example";
request.Data.Properties.Description = "Demonstrates how to share files.";
// Because we are making async calls in the DataRequested event handler,
// we need to get the deferral first.
DataRequestDeferral deferral = request.GetDeferral();
// Make sure we always call Complete on the deferral.
try
{
StorageFile logoFile =
await Package.Current.InstalledLocation.GetFileAsync("Assets\\Logo.png");
List<IStorageItem> storageItems = new List<IStorageItem>();
storageItems.Add(logoFile);
request.Data.SetStorageItems(storageItems);
}
finally
{
deferral.Complete();
}
}
It is critical to place the following statement before any async method is called:
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
You only have half a second to get the whole job done (getting the file, attaching...etc.). If the half-second deadline occurs you'll get this "driving crazy" message. Consider implementing some resumable logic and replace the message with "the attachment is being prepared please try again in a few seconds" (or else).
Your WinRT device might be just slower than your development machine. The latter just does the job before the deadline...

HttpWebRequest for ShoutCast on Windows Phone7

I tring to stream shoutcast stream in my window phone 7 app
I start an async HttpWebRequest like this
//Init Request
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://ACommonoShoutCastUrl:8000");
myHttpWebRequest.Headers["Icy-MetaData"] = "1";
myHttpWebRequest.UserAgent = "WinampMPEG/5.09";
myHttpWebRequest.AllowReadStreamBuffering = true;
//Call
// Create an instance of the RequestState and assign the previous myHttpWebRequest object to its request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result = (IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallBack), myRequestState);
The problem is that the CallBack->RespCallBack is never called...
This code worked for me normally in other environments but not on the phone...
I tired also to use WebClient that seems to stream data,
the problem in this case is that it never call the end OpenReadCompleted because of endelss shoutcast stream
Thanks for support
any help would be appreciated
SHOUTcast implements its own protocol so you can't directly access and play it. You can use DownloadStringAsync (you will need a WebClient instance for this) to download the PLS file and read the URL with the help of RegEx.
When you get the URL, you can read the raw audio data by implementing MediaStreamSource and then use a MediaElement to play the contents.
You can find a sample implementation of MediaStreamSource here.
I just put the following on a page and the callback was called in repsonse to the button click. (I set a break point on the throw statement and it was hit.)
private HttpWebRequest myHttpWebRequest;
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//Init Request
//The following URI was chosen at random
myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1377200");
myHttpWebRequest.Headers["Icy-MetaData"] = "1";
myHttpWebRequest.UserAgent = "WinampMPEG/5.09";
myHttpWebRequest.AllowReadStreamBuffering = true;
// Start the asynchronous request.
myHttpWebRequest.BeginGetResponse(RespCallBack, myHttpWebRequest);
}
private void RespCallBack(IAsyncResult ar)
{
throw new NotImplementedException();
}
I am trying to implement the Shoutcast streaming to my MediaElement via my own MediaStreamSource class. I have a loop in which I am downloading data from Shoutcast server and then set the data to the MediaStreamSource class - this works not perfectly for yet, but I discovered another more important issue. I made a test. I have downloaded a stream to a mp3 (stream is in mp3) file, then put this file to my application and set it to my MediaStreamSource. Here's the code for this:
private void Button_Click(object sender, RoutedEventArgs e)
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
var res = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("Demo1.sample.mp3");
byte[] data = new byte[res.Length];
res.Read(data, 0, data.Length);
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
ShoutcastMediaStreamSource ss = new ShoutcastMediaStreamSource(ms);
player.SetSource(ss);
}
my ShoutcastMediaStreamSource based on MenagedMediaHelpers. So when I put this stream to my ShoutcastMediaStreamSource in debbuger I can see that the method OpenMediaAsync() is called properly, then the GetSampleAsync() is called in a loop by MediaElement, here also everything is fine, but when I run this app there is no sound ! Neither on the emulator nor on the device, and there are no errors. I think, the GetSampleAsync() method is running too fast, bacause for the file (and also stream) duration is about 30 sec., and this app ends after ca. 10 sec. But nevertheless, there should be a sound (scratch).
BUT whats suprising - this app works in Silverlight as Web Page ! The music is playing. I am confused.
Here is allso an app
http://timheuer.com/blog/archive/2010/08/16/download-and-store-media-for-playback-in-windows-phone-7-using-mediastreamsource.aspx
and there is a comment:
If Mp3MediaStreamSource is set as a
source for MediaElement then
MediaElement doesn't play that file
and donesn't show any error in Windows
phone 7 sdk RTM version. In previsios
version it was working but it's not
working with Windows phone 7 sdk final
release.
The callback gets called if you disable read stream buffering:
webRequest.AllowReadStreamBuffering = false;