WebClient class doesn't exist in Windows 8 - c#

I want to use a HTTP webservice, and I've already developed an app for wp7.
I use the WebClient class, but I can not use it for windows 8 ("error: type or namespace can not be found").
What else can I use?
Can you provide me a sample of code?
Does Microsoft have a site to help when a namespace don't exist?

Option 1 : HttpClient if you don't need deterministic progress notification this is what you want use. Example.
public async Task<string> MakeWebRequest()
{
HttpClient http = new System.Net.Http.HttpClient();
HttpResponseMessage response = await http.GetAsync("http://www.example.com");
return await response.Content.ReadAsStringAsync();
}
Option 2: When you need progress notifications you can use DownloadOperation or BackgroundDownloader. This sample on MSDN is a good start.
Option 3: Since you mentioned web service and if it is returning XML you can use XmlDocument.LoadFromUriAsync which will return you an XML document. Example
public async void DownloadXMLDocument()
{
Uri uri = new Uri("http://example.com/sample.xml");
XmlDocument xmlDocument = await XmlDocument.LoadFromUriAsync(uri);
//do something with the xmlDocument.
}
When you are developing for metro .Net framework will be limited compared to the desktop version. If you see namespace not found error it is usually due to this fact. This link on the MSDN has the list of namespaces, classes available for metro.

Related

Implement sending Server Sent Events in C# (no ASP.NET / MVC / ...)

For a project, I need to implement SSE (Server Sent Events) in a C# Application. Although this may sound easy, I've got no clue how to solve this.
As I'm new to C# (though, not new to programming in general) I took an excursion to Google and tried to look for some sample code. From what I've seen so far, I could learn to build a HTTP Server with C# or consume server sent events. But I found nothing about sending SSEs.
What I'm trying to get my head around: how can I keep sending updated data over the incoming request? Normally, you get a request, do your thing and reply. Done, connection closed. But in this case I want to kind of "stick" to the response-stream and send new data through, each time an event in my application fires.
The problem, for me, lies in this event-based approach: it's not some intervall-based polling and updating. It's rather that the app goes like "Hey, something happend. I really should tell you about it!"
TL;DR: how can I hold on to that response-stream and send updates - not based on loops or timers, but each time certain events fire?
Also, before I forget: I know, there are libraries out there doing just that. But from what I've seen so far (and from what I've understood; correct me if I'm wrong) those solutions depend on ASP.NET / MVC / you name it. And as I'm just writing a "plain" C# application, I don't think I meet these requirements.
As for a light-weight server I would go with an OWIN selfhost WebAPI (https://learn.microsoft.com/en-us/aspnet/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api).
A simple server-sent event server action would basically go like:
public class EventController : ApiController
{
public HttpResponseMessage GetEvents(CancellationToken clientDisconnectToken)
{
var response = Request.CreateResponse();
response.Content = new PushStreamContent(async (stream, httpContent, transportContext) =>
{
using (var writer = new StreamWriter(stream))
{
using (var consumer = new BlockingCollection<string>())
{
var eventGeneratorTask = EventGeneratorAsync(consumer, clientDisconnectToken);
foreach (var #event in consumer.GetConsumingEnumerable(clientDisconnectToken))
{
await writer.WriteLineAsync("data: " + #event);
await writer.WriteLineAsync();
await writer.FlushAsync();
}
await eventGeneratorTask;
}
}
}, "text/event-stream");
return response;
}
private async Task EventGeneratorAsync(BlockingCollection<string> producer, CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
producer.Add(DateTime.Now.ToString(), cancellationToken);
await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
}
}
finally
{
producer.CompleteAdding();
}
}
}
The important part here is the PushStreamContent, which basically just sends the HTTP headers and then leaves the connection open to write the data when it is available.
In my example the events are generated in an extra-task which is given a producer-consumer collection and adds the events (here the current time every second) if they are available to the collection. Whenever a new event arrives GetConsumingEnumerable is automatically notified. The new event is then written in the proper server-sent event format to the stream and flushed. In practice you would need to send some pseudo-ping events every minute or so, as streams which are left open for a long time without data being sent over them would be closed by the OS/framework.
The sample client code to test this would go like:
Write the following code in async method.
using (var client = new HttpClient())
{
using (var stream = await client.GetStreamAsync("http://localhost:9000/api/event"))
{
using (var reader = new StreamReader(stream))
{
while (true)
{
Console.WriteLine(reader.ReadLine());
}
}
}
}
This sounds like a good fit for SignalR. Note SignalR is part of the ASP.NET family, however this does NOT require the ASP.NET framework (System.Web), or IIS, as mentioned in comments.
To clarify, SignalR is part of ASP.NET. According to their site:
ASP.NET is an open source web framework for building modern web apps
and services with .NET. ASP.NET creates websites based on HTML5, CSS,
and JavaScript that are simple, fast, and can scale to millions of
users.
SignalR has no hard dependency on System.Web or on IIS.
You can self-host your ASP.Net application (see https://learn.microsoft.com/en-us/aspnet/signalr/overview/deployment/tutorial-signalr-self-host). If you use .net core, it is actually self-hosted by default and runs as a normal console application.

Azure Mobile Service Filter - Removed?

I've been reading about custom auth methods using Azure, and stumbled upon 12 Days of ZUMO. It's an excellent write up, but I can't seem to find anything related to IServiceFilter in the current .Net Client SDK for Azure.
I'm developing a Xamarin app in C#.
Has this functionality been removed or relocated? I have all Azure namespaces referenced and intellisense can't find IServiceFilter or anything else related to service filters.
Thanks for reading.
I currently develop an app for Android on Java (I don't think that library for C# is very different).
And I can access ServiceFilter. But I don't see IServiceFilter.
Namespace - com.microsoft.windowsazure.mobileservices.http.ServiceFilter
Library version - 2.0.2-beta2
In Xamarin you need to use a DelegateHandler instead. This is the standard .net way to filter http traffic.
public class MyLogFilter : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Do any pre-request requirements here
Log.Warning("http request", request.RequestUri.ToString() );
// Request happens here
var response = await base.SendAsync(request, cancellationToken);
// Do any post-request requirements here
Log.Warning("http response", response.StatusCode + " " + response.Content.ReadAsStringAsync().Result);
return response;
}
}
Once you've done that, you just chain the handler when initializing your MobileServiceClient, changing this:
Client = new MobileServiceClient (API_URL, new MyExistingHandler());
to:
Client = new MobileServiceClient (API_URL, new MyLogFilter(), new MyExistingHandler());

Using JSON and HTTP Request in C#

I'm currently developing an Android app and I'm using Connect Android to MS SQL Server Tutorial to link my MSSQL server to the code.
And the first part is good though the second part is using a third party program to code which I don't want to. I want to write the whole code in C# (I'm using Xamarin).
I found out Json.NET / Json.NET for Xamarin website.
Though how am I supposed to use the HTTPUtils and requests in C# ? An example would be great.
Also, I have kind of a newbie question, I'm trying to get to the root of the code I sent, the .aspx file, and I don't quite understand where the web method is, I am used to a seperate .asmx file containing [Web Method]s that define them and then I can use them freely by creating a web reference on an .aspx file, so, where is the web method in the code I sent ?
public static String getJsonData(String webServiceName,String parameter)
{
try
{
String urlFinal=SERVICE_URI+"/"+webServiceName+"?parameter=";
HttpPost postMethod = new HttpPost(urlFinal.trim()+""+URLEncoder.encode(parameter,"UTF-8"));
postMethod.setHeader("Accept", "application/json");
postMethod.setHeader("Content-type", "application/json");
HttpClient hc = new DefaultHttpClient();
HttpResponse response = hc.execute(postMethod);
Log.i("response", ""+response.toString());
HttpEntity entity = response.getEntity();
String responseText = EntityUtils.toString(entity);
string=responseText;
Log.i("Output", ""+responseText);
}
catch (Exception e) {
// TODO: handle exception
}
return string;
}

Parsing JSON from C# in WinRT

I am working on an app for Windows 8. I'm trying to do a search against Twitter via JSON. In an attempt to accomplish this, I was using the following blog post for reference. http://blogs.microsoft.co.il/blogs/bursteg/archive/2008/11/26/twitter-api-from-c-searching.aspx
My problem is, the ASCIIEncoding class doesn't seem to exist in the WinRT framework :(. I saw that UTF8 is available, however, I'm not sure how to use the UTF8 class directly. Can someone please show me how?
Thank you,
For deserializing JSON in .NET (both full .NET and WinRT) I always recommend JSON.NET. It's much easier than DataContractJsonSerializer or any other out of the box solution. And as you can see in the code below, you don't need to define the encoding as they do in the example you provide.
All you need is an object model (use json2csharp to generate it) and a few lines of code:
HttpResponseMessage response = await HttpClient.GetAsync(someUri);
if (response.StatusCode == HttpStatusCode.OK)
{
string responseString = await response.Content.ReadAsStringAsync();
// parse to json
resultItem = JsonConvert.DeserializeObject<T>(responseString);
}
I wrote a more extensive post that shows the different possibilities of JSON parsing in WinRT some time ago.
You can try to use Windows.Data.Json namespace to deserialize ( http://msdn.microsoft.com/en-us/library/windows/apps/windows.data.json(v=VS.85).aspx ). To get your json you can use something like this:
HttpResponseMessage response = await client.GetAsync(url);
string responseText = await response.Content.ReadAsStringAsync();
Just replace ASCIIEncoding.UTF8 with Encoding.UTF8 - they're essentially the same object (the static UTF8 property is defined in the base Encoding class on the desktop framework). And that's available in W8 metro apps.

System.Net.WebClient unreasonably slow

When using the System.Net.WebClient.DownloadData() method I'm getting an unreasonably slow response time.
When fetching an url using the WebClient class in .NET it takes around 10 sec before I get a response, while the same page is fetched by my browser in under 1 sec.
And this is with data that's 0.5kB or smaller in size.
The request involves POST/GET parameters and a user agent header if perhaps that could cause problems.
I haven't (yet) tried if other ways to download data in .NET gives me the same problems, but I'm suspecting I might get similar results. (I've always had a feeling web requests in .NET are unusually slow...)
What could be the cause of this?
Edit:
I tried doing the exact thing using System.Net.HttpWebRequest instead, using the following method, and all requests finish in under 1 sec.
public static string DownloadText(string url)
var request = (HttpWebRequest)WebRequest.Create(url);
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
While this (old) method using System.Net.WebClient takes 15-30s for each request to finish:
public static string DownloadText(string url)
{
var client = new WebClient();
byte[] data = client.DownloadData(url);
return client.Encoding.GetString(data);
}
I had that problem with WebRequest. Try setting Proxy = null;
WebClient wc = new WebClient();
wc.Proxy = null;
By default WebClient, WebRequest try to determine what proxy to use from IE settings, sometimes it results in like 5 sec delay before the actual request is sent.
This applies to all classes that use WebRequest, including WCF services with HTTP binding.
In general you can use this static code at application startup:
WebRequest.DefaultWebProxy = null;
Download Wireshark here http://www.wireshark.org/
Capture the network packets and filter the "http" packets.
It should give you the answer right away.
There is nothing inherently slow about .NET web requests; that code should be fine. I regularly use WebClient and it works very quickly.
How big is the payload in each direction? Silly question maybe, but is it simply bandwidth limitations?
IMO the most likely thing is that your web-site has spun down, and when you hit the URL the web-site is slow to respond. This is then not the fault of the client. It is also possible that DNS is slow for some reason (in which case you could hard-code the IP into your "hosts" file), or that some proxy server in the middle is slow.
If the web-site isn't yours, it is also possible that they are detecting atypical usage and deliberately injecting a delay to annoy scrapers.
I would grab Fiddler (a free, simple web inspector) and look at the timings.
WebClient may be slow on some workstations when Automatic Proxy Settings in checked in the IE settings (Connections tab - LAN Settings).
Setting WebRequest.DefaultWebProxy = null; or client.Proxy = null didn't do anything for me, using Xamarin on iOS.
I did two things to fix this:
I wrote a downloadString function which does not use WebRequest and System.Net:
public static async Task<string> FnDownloadStringWithoutWebRequest(string url)
{
using (var client = new HttpClient())
{
//Define Headers
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
//dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject(responseContent);
return responseContent;
}
Logger.DefaultLogger.LogError(LogLevel.NORMAL, "GoogleLoginManager.FnDownloadString", "error fetching string, code: " + response.StatusCode);
return "";
}
}
This is however still slow with Managed HttpClient.
So secondly, in Visual Studio Community for Mac, right click on your Project in the Solution -> Options -> set HttpClient implementation to NSUrlSession, instead of Managed.
Screenshot: Set HttpClient implementation to NSUrlSession instead of Managed
Managed is not fully integrated into iOS, doesn't support TLS 1.2, and thus does not support the ATS standards set as default in iOS9+, see here:
https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/ats
With both these changes, string downloads are always very fast (<<1s).
Without both of these changes, on every second or third try, downloadString took over a minute.
Just FYI, there's one more thing you could try, though it shouldn't be necessary anymore:
//var authgoogle = new OAuth2Authenticator(...);
//authgoogle.Completed...
if (authgoogle.IsUsingNativeUI)
{
// Step 2.1 Creating Login UI
// In order to access SFSafariViewController API the cast is neccessary
SafariServices.SFSafariViewController c = null;
c = (SafariServices.SFSafariViewController)ui_object;
PresentViewController(c, true, null);
}
else
{
PresentViewController(ui_object, true, null);
}
Though in my experience, you probably don't need the SafariController.
Another alternative (also free) to Wireshark is Microsoft Network Monitor.
What browser are you using to test?
Try using the default IE install. System.Net.WebClient uses the local IE settings, proxy etc. Maybe that has been mangled?
Another cause for extremely slow WebClient downloads is the destination media to which you are downloading. If it is a slow device like a USB key, this can massively impact download speed. To my HDD I could download at 6MB/s, to my USB key, only 700kb/s, even though I can copy files to this USB at 5MB/s from another drive. wget shows the same behavior. This is also reported here:
https://superuser.com/questions/413750/why-is-downloading-over-usb-so-slow
So if this is your scenario, an alternative solution is to download to HDD first and then copy files to the slow medium after download completes.

Categories