Accessing HttpRUntime.Cache in console app - c#

I have a console app that needs to dynamically load all the endpoints in my API app and get the details of the data that is cached.
foreach (var routeTemplate in listRouteTempplates)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/appName/" + routeTemplate );
WebResponse response = null;
Stream dataStream = null;
request.Method = HttpMethod.Get.ToString();
response = request.GetResponse();
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
var count=HttpRuntime.Cache.Count;
}
When invoking each endpoint, the data retrieved is also cached. I confirmed that by calling the endpoints directly (via postman) and checking the cache.
But in the console app, even though the response does have the correct data, the count of items in HttpRuntime.Cache is always zero.
Is there a reason the data is not cached when I call the endpoints in a console app ?
Thanks

The cache in which items are stored lives on the server inside your Web API host. It is then normal that the cache instance that you are checking inside your client console application doesn't have any items in it - those are 2 completely different object instances living in 2 different applications.

Related

Windows Authentication-enabled IIS Site performs differently with 2 different bindings

I have a site set up in IIS 7, and it is using Windows Authentication as the only enabled Authentication Mode. It utilizes a custom .NET 4 Application Pool - the pool uses the default ApplicationPoolIdentity. This site is a C#/ASP.NET application with its own page authorization rules (generated using Iron Speed Designer 9). I have the two bindings set up below:
servicedirectory.sampledomain.com
booking.sampledomain.com
Both of these bindings are mapped to the site on all available IPs on port 80.
For the most part, browsing through either binding works successfully, except for a certain page where I create a WebRequest that fetches another page as a Stream. (I am taking the other page's contents and embedding them as an attachment in an iCal (.ics) file for inclusion in meeting requests. The file is downloaded and sent out by the user)
String request = Request.Url.GetLeftPart(UriPartial.Path).
Replace("Conference.aspx", "Confirmation.aspx") +
"?Conference=" + conference.ConferenceId;
WebRequest webRequest = WebRequest.Create(request);
webRequest.UseDefaultCredentials = true;
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
Stream newStream = webRequest.GetRequestStream();
// Send the data.
newStream.Close();
WebResponse webResponse = webRequest.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
responseStream.CopyTo(ms);
attachmentContent = Convert.ToBase64String(ms.ToArray());
}
responseStream.Close();
The problem is the following: this code succeeds and produces the content from the Confirmation.aspx page as String data (attachmentContent variable) when the user is browsing under the first binding (servicedirectory.sampledomain.com). However, I get a 401.1 error at the WebResponse webResponse = webRequest.GetResponse(); line when browsing via the other binding URL. There are no references in the application source code or web.config to either binding - everything was built with the intention of being deployed to any URL.
Why would two different bindings affect this?

Cancel HTTPWebRequest when server goes down

I have created a Windows Service that calls a API (that returns JSON) with HTTPWebRequest.
The API doesn't return anything until it has something to "deliver". So I set the timeout quite high and lets the request wait until it receivs a response.
The problem is that when I test to turn off or disconnect the server running the API. The HTTPWebRequest doesn't stop the request. So I can't know if the API server has gone down.
The request code:
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(Url);
Request.Method = "POST";
Request.ContentType = "application/x-www-form-urlencoded";
Request.ContentLength = PostData.Length;
Request.Timeout = Timeout;
Request.KeepAlive = true;
using (StreamWriter sw = new StreamWriter(Request.GetRequestStream()))
{
sw.Write(PostData);
}
using (HttpWebResponse Response = (HttpWebResponse)Request.GetResponse())
{
using (StreamReader sr = new StreamReader(Response.GetResponseStream()))
{
ResponseText = sr.ReadToEnd();
}
}
Is there anyway to "break" the request when the requested server goes down?
I have tried using the webbrowser to call the API server and after a while disconnect it and that return an error to the webpage.
you could use a background worker only cecking if the server is online. It has some disatvantages but may work fine.
It is always good to keep the requests asynchronous (See the BeginXXX methods in HttpWebRequest - http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx).
Using the asynchronous APIs ensures that you are not blocked until you get a response from the server.
In addition to using the asynchronous APIs, you can have a heart-beat requests (that could be just a HEAD HTTP request to a ping service on the server, which returns an empty body and HTTP 200 status), to keep track that the server is alive. If this request times out, then server is not alive - in which case, you can cancel / just 'forget' that the request has been made.

Communicating with an ASP website

I have a know a website that contains an open database of the result of an academic test.
http://nts.org.pk/NTSWeb/PPL_30Sep2012_Result/search.asp
I am expert with C# but newbie to web development.
Usually, using web browser, we can enter and roll number and server sends back the result. E.G. Use my Roll Num: 3912125
What I need to do is, use a C# application to communicate this roll null number and get anything, of my result. (any string is excepted, I will parse out my result from that string.)
How do I send query? when I don't know a list of possible query strings.
I tried this code:
string queryString = "RollNo=3912125";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"http://nts.org.pk/NTSWeb/PPL_30Sep2012_Result/search.asp");
request.UseDefaultCredentials = true;
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
byte[] requestBytes = Encoding.UTF8.GetBytes(queryString);
request.ContentLength = requestBytes.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
}
WebResponse response = request.GetResponse();
textBox1.AppendText(((HttpWebResponse)response).StatusDescription);
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
textBox1.AppendText(responseFromServer);
reader.Close();
dataStream.Close();
response.Close();
You have to append the querystring to the url like this:
string queryString = "RollNo=3912125";
string url = String.Format(#"http://foo/search.asp?{0}", queryString);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
You should take a look at the code in my answer to C# https login and download file. It gives a good demonstration of how to perform a POST request. As far as knowing what's valid to use for the query-formatted string in your POST, it's simply a matter of looking for appropriate input elements in the page content. It looks like what you have (RollNo) is correct. You may, however, need to also add the submit button value to your request as well depending on how the server behaves, giving you something like. RollNo=3912125&submit=submit.
You're most of the way there. Your queryString should look like RollNo=3912125&Submit=+Search+. When you are calling WebRequest.Create, the Url should in fact be http://nts.org.pk/NTSWeb/PPL_30Sep2012_Result/result.asp.
The rest of your code should work, though the answer #JamieSee recommended to you has some very good advice about wrapping things in using blocks correctly

Consume Web Service with POST from a WCF Service

So this is my situation. I have to consume a third party web service (not wcf) from another WCF service that will serve as an intermediary between the first service and my web app. The problem is almost every example I have seen on doing this requieres you to Add Web/Service Reference to the app in order to generate the proxy, but I can't add the reference, it returns an error, possibly due to some authentication required.
This service can be consumed only by either GET or POST. I was successful in consuming the service by both GET and POST from an ajax call with jquery in a web page, but I don't know how to consume the service from inside a wcf service in c#.
An example GET request from the service is:
http://webservice.server.com/services/myservice?user=[username]&password=[password]&value1=[somevalue]&value2=[anothervalue]
The response is an xml with the status code of the operation and a status message, which I then proceed to save to a database.
How might I go about doing this?
Thank you for any help...
SOLUTION
Thanks to Sean for pointing me in the right direction. How I did it:
Reference article: How to use HttpWebRequest to send POST request to another web server
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "username=" + username;
postData += ("&password=" + password);
postData += ("&value1=" + val1);
postData += ("&value2=" + val2);
byte[] data = encoding.GetBytes(postData);
// Prepare POST web request...
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create(new Uri("http://webservice.server.com/services/myservice"));
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
Stream newStream = myRequest.GetRequestStream();
// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();
// Get response
using (HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Read the whole contents and return as a string
result = reader.ReadToEnd();
}
XDocument doc = XDocument.Parse(result);
// Read XML
Please if you have any comments on my solution, objections or improvements, all comments are welcomed.
I think you'd want to take a look at the HttpRequest class:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.aspx
If you can't add the web service reference (I would investigate further why you can't do this first) I am afraid you'll have to do this manually issuing an HTTP Request manually using the WebClient class WebClient or the HttpReqest class as Sean suggests

Can I send an empty HTTP POST WebRequest object from C# to IIS?

Do I need to just slap some random garbage data in a WebRequest object to get by the HTTP status code 411 restriction on IIS?
I have an HttpPost action method in an MVC 3 app that consumes a POST request with all the relevant information passed in the querystring (no body needed).
[HttpPost] public ActionResult SignUp(string email) { ... }
It worked great from Visual Studio's built in web host, Cassini. Unfortunately, once the MVC code was live on IIS [7.5 on 2008 R2], the server is pitching back an HTTP error code when I hit it from my outside C# form app.
The remote server returned an error:
(411) Length Required.
Here is the calling code:
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader responseReader = new StreamReader(responseStream)) {
// Do something with responseReader.ReadToEnd();
}
Turns out you can get this to go through by simply slapping an empty content length on the request before you send it.
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
request.ContentLength = 0;
Not sure how explicitly giving an empty length vs. implying one makes a difference, but IIS was happy after I did. There are probably other ways around this, but this seems simple enough.
I believe you are required to set a Content-Length header anytime you post a request to a web server:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.contentlength.aspx
You could try a GET request to test it.

Categories