|
by
kirupa | 11 September 2010
Have questions? Discuss this
Windows Phone tutorial
with others on the forums.
If you are going to be performing any action on a file, you want to make sure
the file exists first. This is easier for files stored locally on your machine
where you can simply do a File.Exists call
and...call it a day.
Things are a little bit more tricky when you try to check
if a remote file such as something on a HTTP server exists
though. Given the nature of requests traveling over a
network, there are two things to keep in mind that make
performing this check non-trivial:
- You want to make sure your application remains
performant while the network request is being made.
- You do not want to download the entire remote file
when checking if it exists.
Given those two requirements, you have to do a little
more work than just using a simple
File.Exists call. Instead, you have to construct a
web request yourself and listen for the appropriate response
to verify that the remote file exists.
In this article,
since it is more of a deconstruction as opposed to a
tutorial, below you will find a project containing the code for both
creating and sending the web request and listening for the
response:
Download and extract the above files to a
location on disk. Make sure you have everything you
need to get started with Windows Phone development,
open the solution in Visual Studio, and look in
MainPage.xaml.cs.
MainPage.xaml.cs contains the sample code that does the bare
minimum for checking if a remote file exists:
- public
MainPage()
- {
- InitializeComponent();
-
- Uri
filePath
=
new Uri("http://www.kirupa.com/blah/");
-
- HttpWebRequest
fileRequest
=
HttpWebRequest.CreateHttp(filePath);
- fileRequest.Method
=
"HEAD";
-
- fileRequest.BeginGetResponse(new
AsyncCallback(WebRequestCallBack),
fileRequest);
- }
-
- void
WebRequestCallBack(IAsyncResult
result)
- {
- HttpWebRequest
resultInfo
= (HttpWebRequest)
resultInfo.AsyncState;
- HttpWebResponse
response;
-
- try
- {
- response
=
(HttpWebResponse)request.EndGetResponse(result);
-
- string
statusCode
=
response.StatusCode.ToString();
- }
- catch
(WebException
e)
- {
- string
statusCode
=
e.Message;
- }
- }
For the rest of this page, let's go through and
understand what all of the above code does so that you can
easily modify and port it for your own needs.
The first thing we do is adding a using statement for the
System.Net namespace:
- using
System.Net;
The reason we do that is because a handful of the classes
we will be using live in the System.Net namespace.
The next set of code is where things begin to get
interesting:
- Uri
filePath
= new
Uri("http://www.kirupa.com/blah/moo.zip");
-
- HttpWebRequest
fileRequest
=
HttpWebRequest.CreateHttp(filePath);
- fileRequest.Method
=
"HEAD";
In the first line, I create my Uri object called filePath.
In the Uri constructor, I specify the URL to the file I am interested in
checking whether it exists or not.
The second line is where the Uri object becomes more
useful! Here, I
construct my HttpWebRequest object called
fileRequest. Notice that I
pass in the filePath Uri
object I created earlier when initializing this request. The
reason is that I am using the CreateHttp method from the
HttpWebRequest class to tell my request what location to
send the request to, and the filePath Uri object I created
earlier contains that information.
The last step in actually making the request is
specifying what HTTP method to use as part of my request:
- fileRequest.Method
=
"HEAD";
The methods you can commonly use are HEAD, GET, PUT,
POST, and DELETE. I am using the
HEAD method because I just want to know more about this
file without actually downloading the file.
Once the request has been created, it's time to send it
off:
- fileRequest.BeginGetResponse(new
AsyncCallback(WebRequestCallBack),
fileRequest);
The BeginGetResponse method is responsible for sending a
request asynchronously to a URL that you
specify. What asynchronous brings to the table is that your UI will remain responsive
even when a part of your application is dealing with sending
the request and waiting for a response.
The BeginGetResponse method takes one argument, and that argument is an
asynchronous callback function:
- fileRequest.BeginGetResponse(new
AsyncCallback(WebRequestCallBack), fileRequest);
I create a new AsyncCallback object that defines a
handler for the callback and takes our
fileRequest HttpWebRequest
object as its argument. When a response is heard back, the
WebRequestCallBack method
will get fired. Let's look at that method next.
Right now, our web requesst has been made, and the
response is handled by the WebRequestCallBack method:
- void
WebRequestCallBack(IAsyncResult
result)
- {
- HttpWebRequest
resultInfo
= (HttpWebRequest)result.AsyncState;
- HttpWebResponse
response;
-
- try
- {
- response
=
(HttpWebResponse)
resultInfo.EndGetResponse(result);
-
- string
statusCode
=
response.StatusCode.ToString();
- }
- catch
(WebException
e)
- {
- string
statusCode
=
e.Message;
- }
- }
This method brings with it one argument, and that is a
result object whose type
is IAsyncResult. This result object contains a response back
from the web server that you sent a request to. In the first
two lines, I basically unwrap the response into a form that
we can make sense of:
- HttpWebRequest
resultInfo
= (HttpWebRequest)result.AsyncState;
- HttpWebResponse
response;
The first thing I do is get our result information
wrapped back into the original HttpWebRequest format through
a variable called resultInfo.
As you will see shortly, I am doing this so that I can
formally conclude my web request.
Finally, to help parse the response from the request, I
declare a HttpWebResponse object very cleverly called,
response!
The final piece of the puzzle lies in the next few lines
where I dig into the response and get the answer that you
have been searching your entire life for, "Does that file
exist on the server?"
These lines are:
- try
- {
- response
= (HttpWebResponse)
resultInfo.EndGetResponse(result);
-
- string
statusCode
=
response.StatusCode.ToString();
- }
- catch
(WebException
e)
- {
- string
statusCode
=
e.Message;
- }
Because this a very exception-happy set of code, I wrap
everything into a try/catch
statement. The try part
deals with handling the case where the file is found:
- response
= (HttpWebResponse)
resultInfo.EndGetResponse(result);
-
- string
statusCode
=
response.StatusCode.ToString();
Notice that I first take our resultInfo object and call
the EndGetResponse method to end the web request started off
earlier by our BeginGetResponse. The EndGetResponse method
takes an IAsyncResult object as its argument, and it returns
data back in the form of a WebResponse. Fortunately our
result and
response objects have both
bases of that covered!
Now, all that is left is to read the HTTP status code
that was returned:
- string
statusCode
=
response.StatusCode.ToString();
The StatusCode property returns the appropriate
HttpStatusCode value which I bludgeon by just ToString-ing
it into something I can read. You can handle this more
appropriately if you feel the need to of course.
In the case that a response was not successful such as
the file not being found, the code in the
catch part will run:
- catch
(WebException
e)
- {
- string
statusCode
=
e.Message;
- }
I constrain the exception by only listening for a
WebException, and I all I am doing in the body of the catch
statement is just seeing what the message returned by the
exception is.
And with that, you are done!
Need Help?
If you have questions, need some assistance on this topic, or just want to
chat - please drop by our friendly forums
and post your question. There are a lot of knowledgeable and witty people who
would be happy to help you out. Plus, we have a
large collection of smileys
you can use

Share
Did you enjoy reading this and found it useful? If so, please share it with
your friends:
If you didn't like it, I always like to hear how I can do better next time.
Please feel free to contact me directly at kirupa[at]kirupa.com.
Cheers!
|