Call a webpage from c# in code - c#

I need a way of calling a web page from inside my .net appliction.
But i just want to send a request to the page and not worry about the response.
As there are times when the response can take a while so i dont want it to hang the appliction.
I have been trying in side the page_load event
WebClient webC = new WebClient();
Uri newUri = new Uri("http://localhost:49268/dosomething.aspx");
webC.UploadStringAsync(newUri, string.Empty);
Even though its set to Async, it still seams to hang as the page wont finish rendering until the threads have finsished

This should work for you:
System.Net.WebClient client = new System.Net.WebClient();
client.DownloadDataAsync(new Uri("http://some.url.com/some/resource.html"));
The WebClient class has events for notifying the caller when the request is completed, but since you don't care there shouldn't be anything else to it.

Doak, Was almost there, but each time I put any of the request in a sepreate thread the page still wouldn't render until all the thread had finished running.
The best way I found was adjusting Doak's method, and just sticking a timeout in there and swallowing the error.
I know its a hack but it does work :P
WebRequest wr = WebRequest.Create("http://localhost:49268/dostuff.aspx");
wr.Timeout = 3500;
try
{
HttpWebResponse response = (HttpWebResponse)wr.GetResponse();
}
catch (Exception ex)
{
//We know its going to fail but that dosent matter!!
}

For not having you application to hang you will need to call the method from a Thread.
For the HTTP request without an answer, something like that should do the job:
Thread myThread = new Thread(new ThreadStart(myMethodThatDoHttp));
myThread.Start();
public void myMethodThatDoHttp()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www..com");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}

Look at System.Net.WebClient, specifically use the DownloadDataAsync() method to send the request without blocking the rest of the app.

To have this process without interrupting the page flow of your current page I would recommend creating a WCF service that will execute the code for you. Have the service set to use 1 way calls and on the page initiate an Ajax call to the service.

As far as I can see the 'BeginGetResponse'-method and the 'EndGetResponse'-method of the HttpWebRequest-object (gained through the call of WebRequest.Create), resp. the BeginGetRequestStream-/EndGetRequestStream methods, HERE aren't reflected yet, - although they are EXLPLICITLY marked for an "async request" in the docs:
For .Net 2.0
For .Net 4.0
No clue, how that works.
If the page to call is on the same IIS/App. as the calling, you could write an Filter, that ends all service for this request to client (Your 'calling' aspx-page), if the map-string contains the spec for the page to call (in ISAPI-cpp: "return SF_STATUS_REQ_FINISHED;") But perhaps Your asp/x/-script-execution in the called page is killed too. Question of check.
Consider using server-side include directives (less conditionable) or dynamically call an .asp file by using Server.Execute.
Not really async, but maybe worthy: State explicitly by an EARLY Response.End() (or similar) IN THE CALLED PAGE to the system, that NO FURTHER RESPONSE is to be expected, mainly NOT to the caller. Then do Your stuff ongoing in the CALLED page's scripts. At least the time-slip to await the sync-call's ending could be minimized by fac of 10, 100 or so.

Use System.Net.WebClient.DownloadDataAsync/DownloadFileAsync in conjunction with DownloadDataCompleted/DownloadFileCompleted.

Related

Windows Phone 8 - waiting for HttpWebRequest to finish in Application_Closing method

I have a component in my Windows Phone 8 app (let's call it RequestSender), which contains a queue of requests, as well as a Thread (let's call it SenderThread), which reads the queue (blocks on Dequeue), and sends the requests using HttpWebRequest.
The HttpWebRequest inside the SenderThread's method is done in a way that simulates a synchronous call, like so:
_requestWaitHandle.Reset();
IAsyncResult respResult = webReq.BeginGetResponse(GetResponseStreamCallback, null);
_requestWaitHandle.Wait();
HttpWebResponse response = webReq.EndGetResponse(respResult) as HttpWebResponse;
The only thing which the callback method does here is setting the _requestWaitHandle (which is a ManualResetWaitHandleSlim by the way).
All this works fine, except for the situation, when I try to send a "goodbye" request when the app is being closed after the user presses the "Back" hardware button.
I tried to simply enqueue the "goodbye" request in Application_Closing method, and then call a "Stop" on RequestSender. The Stop method would signal the thread that it should exit (by setting an appropriate flag), and then call Join() on the thread.
The SenderThread should finish processing the web request, check the "stop" flag, and simply exit. That's the theory.
In practice, the "goodbye" request gets enqueued, starts being processed, but the HttpWebRequest simply hangs on BeginGetResponse and never exits. What may be causing this?
In one of the answers to the following question: Question about HttpWebRequest it's stated, that "The HttpWebRequest use UI thread to process a request, don't ask me why.". Is this true? How can I avoid this and simply make the web request? Do I need to use something else than HttpWebRequest for this?
I needed the exact same thing as you and I tested everything in the platform, but only sockets got the job done.
If you want to try your luck with sockets - here's what I used (just delete the JSON-related stuff). And you'll also need this library.
The usage is something like this:
var http = new HttpSocketConnection();
var postBody = new HttpPostBodyBuilder.*Body();
// Here you set some parameters
using (var bodyStream = postBody.PrepareData()) {
var req = new HttpMessage.Request(bodyStream, "POST");
req.ContentLength = bodyStream.Length;
req.ContentType = postBody.GetContentType();
// send request
var response = http.Send(url, req);
}
Hope this helps. :)
P.S. The code is far from perfect, but it did what I needed, and you know the old saying: "If something's not broken, don't fix it". :)

C#: will there be a recursion limit issue with this approach borrowed from javascript

Wondering if an approach that's possible in javascript is OK to use in C#.
In a javascript application, when a large number of web requests have to be made one after the other, the UI can be kept responsive by eschewing a for-loop, and instead, using a stack (an array) and events. The next URL is popped from the array in the success eventhandler, which keeps making another request until the stack is empty. Can a similar approach be taken in C# with a Stack? Is the following legit?
urlStack .... // stack of urls
myRequestMaker = new WebRequestMaker(); // my custom object
myRequestMaker.ResponseReceived += (s,e) =>
{
// e contains info whether the request succeeded, failed, or timed out
url = pop another url from urlStack if it's not empty
(s as WebRequestMaker).MakeWebRequest(url);
}
url = pop first url from urlStack
myRequestMaker.MakeWebRequest(url);
(The ReponseReceived event is raised by the WebRequestMaker object also when the request times out, BTW)
In javascript, you can hit maximum recursion limits using this approach, and to get around that you can wrap the method invocation, made inside the success eventhandler, in a SetTimeout. Will invokving myRequestMaker's MakeWebRequest method inside the ResponseReceived eventhandler run into analogous issues?
Yes, your code will eventually hit StackOverflowException. You can simulate setTimeout behaviour using the System.Task class that runs code asynchronously:
myRequestMaker.ResponseReceived += (s,e) =>
{
// e contains info whether the request succeeded, failed, or timed out
url = pop another url from urlStack if it's not empty
Task.Run(() => (s as WebRequestMaker).MakeWebRequest(url));
}
(of course, your urlStack now should be a concurrent to avoid racing conditions)
Optimally, you would not use the code above, but implement a MakeWebRequestAsync method that gets your job done asynchronously. Most built-in long-running/blockin methods (such as reading and writing from/to streams) in .Net already implement such a method, so if your WebRequestMaker is actually using a System.Net.WebClient you can call the async version. More information about tasks and async/await can be found in MSDN.
Yes it will, every function call pushed to the call stack and poped when it finishes.
The error you mention is fired when the call stack is full, not in javascript, in most languages (in fact I don't know any that doesn't).
You should apply the same logic as you do in Javascript here.

Calling a webservice async

Long post.. sorry
I've been reading up on this and tried back and forth with different solutions for a couple of days now but I can't find the most obvious choice for my predicament.
About my situation; I am presenting to the user a page that will contain a couple of different repeaters showing some info based on the result from a couple of webservice calls. I'd like to have the data brought in with an updatepanel (that would be querying the result table once per every two or three seconds until it found results) so I'd actually like to render the page and then when the data is "ready" it gets shown.
The page asks a controller for the info to render and the controller checks in a result table to see if there's anything to be found. If the specific data is not found it calls a method GetData() in WebServiceName.cs. GetData does not return anything but is supposed to start an async operation that gets the data from the webservice. The controller returns null and UpdatePanel waits for the next query.
When that operation is complete it'll store the data in it's relevant place in the db where the controller will find it the next time the page asks for it.
The solution I have in place now is to fire up another thread. I will host the page on a shared webserver and I don't know if this will cause any problems..
So the current code which resides on page.aspx:
Thread t = new Thread(new ThreadStart(CreateService));
t.Start();
}
void CreateService()
{
ServiceName serviceName = new ServiceName(user, "12345", "MOVING", "Apartment", "5100", "0", "72", "Bill", "rate_total", "1", "103", "serviceHost", "password");
}
At first I thought the solution was to use Begin[Method] and End[Method] but these don't seem to have been generated. I thought this seemed like a good solution so I was a little frustrated when they didn't show up.. is there a chance I might have missed a checkbox or something when adding the web references?
I do not want to use the [Method]Async since this stops the page from rendering until [Method]AsyncCompleted gets called from what I've understood.
The call I'm going to do is not CPU-intensive, I'm just waiting on a webService sitting on a slow server, so what I understood from this article: http://msdn.microsoft.com/en-us/magazine/cc164128.aspx making the threadpool bigger is not a choice as this will actually impair the performance instead (since I can't throw in a mountain of hardware).
What do you think is the best solution for my current situation? I don't really like the current one (only by gut feeling but anyway)
Thanks for reading this awfully long post..
Interesting. Until your question, I wasn't aware that VS changed from using Begin/End to Async/Completed when adding web references. I assumed that they would also include Begin/End, but apparently they did not.
You state "GetData does not return anything but is supposed to start an async operation that gets the data from the webservice," so I'm assuming that GetData actually blocks until the "async operation" completes. Otherwise, you could just call it synchronously.
Anyway, there are easy ways to get this working (asynchronous delegates, etc), but they consume a thread for each async operation, which doesn't scale.
You are correct that Async/Completed will block an asynchronous page. (side note: I believe that they will not block a synchronous page - but I've never tried that - so if you're using a non-async page, then you could try that). The method by which they "block" the asynchronous page is wrapped up in SynchronizationContext; in particular, each asynchronous page has a pending operation count which is incremented by Async and decremented after Completed.
You should be able to fake out this count (note: I haven't tried this either ;) ). Just substitute the default SynchronizationContext, which ignores the count:
var oldSyncContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
var serviceName = new ServiceName(..);
// Note: MyMethodCompleted will be invoked in a ThreadPool thread
// but WITHOUT an associated ASP.NET page, so some global state
// might be missing. Be careful with what code goes in there...
serviceName.MethodCompleted += MyMethodCompleted;
serviceName.MethodAsync(..);
}
finally
{
SynchronizationContext.SetSynchronizationContext(oldSyncContext);
}
I wrote a class that handles the temporary replacement of SynchronizationContext.Current as part of the Nito.Async library. Using that class simplifies the code to:
using (new ScopedSynchronizationContext(new SynchronizationContext()))
{
var serviceName = new ServiceName(..);
// Note: MyMethodCompleted will be invoked in a ThreadPool thread
// but WITHOUT an associated ASP.NET page, so some global state
// might be missing. Be careful with what code goes in there...
serviceName.MethodCompleted += MyMethodCompleted;
serviceName.MethodAsync(..);
}
This solution does not consume a thread that just waits for the operation to complete. It just registers a callback and keeps the connection open until the response arrives.
You can do this:
var action = new Action(CreateService);
action.BeginInvoke(action.EndInvoke, action);
or use ThreadPool.QueueUserWorkItem.
If using a Thread, make sure to set IsBackground=true.
There's a great post about fire and forget threads at http://consultingblogs.emc.com/jonathangeorge/archive/2009/09/10/make-methods-fire-and-forget-with-postsharp.aspx
try using below settings
[WebMethod]
[SoapDocumentMethod(OneWay = true)]
void MyAsyncMethod(parameters)
{
}
in your web service
but be careful if you use impersonation, we had problems on our side.
I'd encourage a different approach - one that doesn't use update panels. Update panels require an entire page to be loaded, and transferred over the wire - you only want the contents for a single control.
Consider doing a slightly more customized & optimized approach, using the MVC platform. Your data flow could look like:
Have the original request to your web page spawn a thread that goes out and warms your data.
Have a "skeleton" page returned to your client
In said page, have a javascript thread that calls your server asking for the data.
Using MVC, have a controller action that returns a partial view, which is limited to just the control you're interested in.
This will reduce your server load (can have a backoff algorithm), reduce the amount of info sent over the wire, and still give a great experience to the client.

SL 4: simple file upload, why is this not working?

I am not getting any exception in the following code, however I also don't see the file which is suppose to be uploaded to the server (in this case a localhost) - could someone please point out the mistake?
As an add on, I need a simple silverlight file uploader with a progress bar, but I am having a really hard time try using the ones on the codeplex, Does anyone here has a good one for SL4?
public FileStream MyFS { get; set; }
private void UploadFile()
{
FileStream _data; // The file stream to be read
_data = MyFS;
string uploadUri;
uploadUri = #"http://localhost/MyApplication/Upload/Images/testXRay.gif";
byte[] fileContent = new byte[_data.Length]; // Read the contents of the stream into a byte array
int dataLength = int.Parse(_data.Length.ToString());
_data.Read(fileContent, 0, dataLength);
WebClient wc = new WebClient();
wc.OpenWriteCompleted += new OpenWriteCompletedEventHandler(wc_OpenWriteCompleted);
Uri u = new Uri(uploadUri);
wc.OpenWriteAsync(u, null, fileContent); // Upload the file to the server
}
void wc_OpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e) // The upload completed
{
if (e.Error == null)
{
// Upload completed without error
}
}
Thanks,
Voodoo
You are trying to write to a server URL that is an image, not a service:
uploadUri = #"http://localhost/MyApplication/Upload/Images/testXRay.gif";
...
Uri u = new Uri(uploadUri);
wc.OpenWriteAsync(u, null, fileContent);
You can't just write a file (via HTTP) to a webserver like that. The receiving URL needs to be a web service designed to accept the incoming byte stream.
I am sure there are better examples about, but try this link first.
Another problem with your code is that you haven't tried to write the file at all.
This line doesn't do what you think:
wc.OpenWriteAsync(u, null,
fileContent); // Upload the file to
the server
The call signature is OpenWriteAsync(URI, HTTPMETHOD, UserToken).
Let me break that down a little. URI I think you have. The HTTPMETHOD let's you set whether you are doing a post or a get. Probably you want to do an HttpPost. Finally that last item isn't for pushing the filecontent. It is more of a state variable so you can keep track of the request (more on this in a moment).
The way the HTTP stack works in Silverlight is that everything is asynchronous. So you in your case you are setting up a request and then telling the runtime that you want to write some data to the request. That is what your call does. It goes out and sets up to let you make a request (which may all happen on a background thread not the thread where the UI gets updated). Once this is set up it will call your callback event with a stream which you can write to. One of the things it sends back to you is that state variable (the UserToken) which gives you the ability to know which request it responded back to you with (which means that you could send multiple files back to the server at the same time).
It will also exposes a few other events that you can use to see if everything worked Ok (like you can get a response from the your call and see what the status code was --which will tell you if everything was successful or not). BTW, with every callback it sends that UserToken variable so your app can keep track of which request was being responded to (if there are more than one going on right now).
The links that the last guy provided should help you out some. He is right too, you need something on the server setup to respond to the request or rather you typically want to do this. You can set up a folder to allow you to push data directly to it, but honestly you don't want to do this as you would be opening up your server for hackers to exploit.

WebService Async method question

in playing around with the idea of using a webservice for my project I noticed that a couple of properties ( method/event ) were automatically created for me. I can see the purpose of the Completed event but I am not sure where the Async method would be used.
webmethod declaration:
[WebMethod]
public string HelloBrad()
{
return "Hello Brad";
}
Consumption of service in codebehind
localhost.Service1 service = new localhost.Service1();;
service.HelloBradAsync
service.HelloBradCompleted
service.HelloBrad
could somebody please explain the usage of the HelloBradAsync method.
Thanks
Async methodology allows your code to continue executing while the server is processing the message. Using your normal service.HelloBrad code, the thread will block until the webservices returns a response.
Instead, if you call HelloBradAsync, it immediately moves on to your next line of code. When the server is done, it will respond inside the "HelloBradCompleted" event.
This is so that the webservice doesn't block your primary thread while it executes, and is definitely the proper way of doing business. It might require a change in your programming paradigm, but you'll find the benefits outweigh the costs.

Categories