How do I get httprequest content to display on localhost in c#? - c#

I have an incoming POST request from a program that consists of JSON data.
This is my server code:
static HttpListener _httpListener = new HttpListener();
static void ResponseThread()
{
while (true)
{
HttpListenerContext context = _httpListener.GetContext(); // get a context
// Now, you'll find the request URL in context.Request.Url
HttpListenerRequest request = context.Request;
string test = "";
using (http://System.IO (http://System.IO).Stream body = request.InputStream) // here we have data
{
using (http://System.IO (http://System.IO).StreamReader reader = new http://System.IO (http://System.IO).StreamReader(body, request.ContentEncoding))
{
test = reader.ReadToEnd();
}
}
Console.WriteLine(test);
byte[] _responseArray = Encoding.UTF8.GetBytes(test); // get the bytes to response
context.Response.OutputStream.Write(_responseArray, 0, _responseArray.Length); // write bytes to the output stream
context.Response.KeepAlive = false; // set the KeepAlive bool to false
context.Response.Close(); // close the connection
Console.WriteLine("Respone given to a request.");
}
}
static void Main(string[] args)
{
Console.WriteLine("Starting server...");
_httpListener.Prefixes.Add("http://localhost:5000/ (http://localhost:5000/)"); // add prefix "http://localhost:5000/ (http://localhost:5000/)"
_httpListener.Start(); // start server (Run application as Administrator!)
Console.WriteLine("Server started.");
Thread _responseThread = new Thread(ResponseThread);
_responseThread.Start(); // start the response thread
}
This is the posting code i'm using outside of the server code in a different project
static string httpPost(string json)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:5000/");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
and I want to display the "test" variable in my browser but for right now it isn't working at all. Nothing is displayed but if I just send some html it works. Is there anyway to get this working or parse it out so that it does work?

To augment my comment on your question, here's a "Hello World" of sorts using the Owin self hosted server. It mimics what your question was trying to do. First install NuGet package Microsoft.Owin.SelfHost. Then include the System.Net.Http and System.Net.Http.Formatting .Net framework references. Included also is a code example to call the self-hosted server.
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace StackOverflowAnswer
{
class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<RespondToRequestMiddleware>();
}
}
class RespondToRequestMiddleware : OwinMiddleware
{
public RespondToRequestMiddleware(OwinMiddleware next)
: base(next)
{
}
public async override Task Invoke(IOwinContext context)
{
// Perform request stuff...
// Could verify that the request Content-Type == application/json
// Could verify that the request method was POST.
bool isPost = context.Request.Method == "POST";
string test = null;
if (isPost)
{
using (StreamReader reader = new StreamReader(context.Request.Body))
{
test = await reader.ReadToEndAsync();
}
}
await Next.Invoke(context); // pass off request to the next middleware
if (isPost)
{
// Perform response stuff...
context.Response.ContentType = "application/json";
context.Response.StatusCode = 200;
await context.Response.WriteAsync(test);
Console.WriteLine("Response given to a request.");
}
}
}
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:5000/";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine($"Listening on {url}...");
using (HttpClient httpClient = new HttpClient())
{
string json = "{\"key\":\"value\", \"otherKey\":\"secondValue\"}";
// Typically use the extensions in System.Net.Http.Formatting in order to post a strongly typed object with HttpClient.PostAsJsonAsync<T>(url)
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = httpClient.PostAsync(url, content).Result; // IMPORTANT: use await in an async method in the real world.
if (response.IsSuccessStatusCode)
{
string responseJson = response.Content.ReadAsStringAsync().Result; // Again: use await in an async method in the real world.
Console.WriteLine(responseJson); // In your method, return the string.
}
else
{
Console.WriteLine($"Unsuccessful {response.StatusCode} : {response.ReasonPhrase}");
}
}
Console.ReadLine(); // keep console from closing so server can keep listening.
}
}
}
}
In action:
Check out the Microsoft Owin/Katana site for more info.

Related

HttpClient gets response 404 from nominatim

I would like to convert several data sets with a service in the background through Nominatim server. Now I've invested a lot of time to get an answer from the nominatim with the Http client class. Unfortunately, I only ever get a 404 error
Here is my sample code:
namespace ConsoleApp7
{
internal class Program
{
static void Main(string[] args)
{
Task t = new Task(DownloadPageAsync);
t.Start();
Console.WriteLine("Downloading page...");
Console.ReadLine();
}
static async void DownloadPageAsync()
{
// ... Target page.
string page = "https://nominatim.openstreetmap.org/reverse?
format=geocodejson&lat=60.2299&lon=11.1663";
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await
client.GetAsync(page))
using (HttpContent content = response.Content)
{
// ... Read the string.
string result = await content.ReadAsStringAsync();
// ... Display the result.
if (result != null)
{
Console.WriteLine(result);
}
}
}
}
}
I'm happy about any help!
Many thanks
The problem is that website doesn't allow any default http request without user agent. You can solve this adding a useragent to your request. Code like below:
static void Main(string[] args)
{
Task t = new Task(DownloadPageAsync);
t.Start();
Console.WriteLine("Downloading page...");
Console.ReadLine();
}
static async void DownloadPageAsync()
{
// ... Target page.
string page = "https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=60.2299&lon=11.1663";
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (compatible; AcmeInc/2.0)");
using (HttpResponseMessage response = await
client.GetAsync(page))
using (HttpContent content = response.Content)
{
// ... Read the string.
string result = await content.ReadAsStringAsync();
// ... Display the result.
if (result != null)
{
Console.WriteLine(result);
}
}
}
}
You simply need to set a User-Agent
var page = "https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=60.2299&lon=11.1663";
// ... Use HttpClient.
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "WHATEVER VALUE");
using var response = await client.GetAsync(page);
using var content = response.Content;
// ... Read the string.
var result = await content.ReadAsStringAsync();
// ... Display the result.
if (result != null) Console.WriteLine(result);

why is this vsts rest api returning 404?

I was following this example to use the VSTS REST API:
https://learn.microsoft.com/en-us/rest/api/vsts/search/code%20search%20results/fetch%20code%20search%20results?view=vsts-rest-4.1
The following url points directly to MyService.MyController in my org's VSTS:
https://my-corp.visualstudio.com/DefaultCollection/USOpsInfrastructure/USOpsInfrastructure%20Team/_git/MyService?path=%2FMyService.UI%2FControllers%2FMyController.cs&version=GBmaster
I tried to follow the example code with my implentation code below but a 404 response is returned without a detailed message. Any idea what the issue might be or how to debug?
private static async Task FindMyControllerRefs()
{
var baseUrl = "https://my-corp.almsearch.visualstudio.com";
using (var client = GetHttpClient(baseUrl))
{
var request = "{ \"searchText\": \"MyController\" }";
var projectUri = "/USOpsInfrastructure/USOpsInfrastructure%20Team/_git/MyService";
var searchUri = "/_apis/search/codesearchresults?api-version=4.1-preview.1";
var fullUri = projectUri + searchUri;
var response = await client.PostAsJsonAsync(fullUri, request);
//process the response
if (response.IsSuccessStatusCode)
{
var result = (await response.Content.ReadAsAsync<string>());
}
else //not 200
{
var message = await response.Content.ReadAsStringAsync();
}
}
}
private static HttpClient GetHttpClient(string baseUrl)
{
var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new Uri(baseUrl);
client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
The Code search REST API should be :
POST https://XXX.almsearch.visualstudio.com/{Project}/_apis/search/codesearchresults?api-version=4.1-preview.1
In you scenario please confirm what's the team project name: USOpsInfrastructure or MyService. If you are not sure about that, then you can have a try for each of them.
Besides, base on my test you need to add the "$top": 10 (you can change the number as needed) in the request body:
var request = "{ \"searchText\": \"MyController\",\"$top\": 10 }";
Below code works on my side: (Project name is "Git" in below sample)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace CodeSearch
{
class Program
{
public static void Main()
{
Task t = CodeSearch();
Task.WaitAll(new Task[] { t });
}
private static async Task CodeSearch()
{
try
{
var username = "username";
var password = "Password/PAT";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
string url = "https://{instance}.almsearch.visualstudio.com/Git/_apis/search/codesearchresults?api-version=4.1-preview.1";
var content = new StringContent("{\"searchText\": \"OwinStartupAttribute\", \"$top\": 10}", Encoding.UTF8, "application/json");
using (HttpResponseMessage response = client.PostAsync(url, content).Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
Console.ReadLine();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}

HttpListenerRequest read InputStream slow when using HttpClient or WebRequest

I have a HttpListener which is waiting for incoming requests. The curious thing is that when I send a request with the HttpClient or WebRequest class, the reading/decoding of the stream takes around 350ms, while sending the same request with Insomnia (https://insomnia.rest/) it only takes 500ticks!!
Can someone explain to me where is my fault?!
HttpClient
private readonly HttpClient _Client = new HttpClient();
private async void HttpClientMethod(string jsonContent)
{
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, _BaseUrl);
message.Content = new StringContent(jsonContent);
HttpResponseMessage result = await _Client.SendAsync(message);
string content = await result.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
WebRequest Client
private string WebRequestMethod(string jsonContent)
{
WebRequest request = WebRequest.Create(_BaseUrl);
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = jsonContent;
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
return responseFromServer;
}
Host
private void ReadInputStream(HttpListenerRequest request)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string text;
using (StreamReader reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
text = reader.ReadToEnd();
}
stopwatch.Stop();
}
HttpClient | WebRequest
Insomnia
Insonmia Body | JSONContent
Sample Project
Just create a new Console App
Program.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace ApiTest
{
class Program
{
static readonly ApiHost _ApiHost = new ApiHost();
static readonly HttpClient _Client = new HttpClient();
static void Main(string[] args) => MainAsync(args).GetAwaiter().GetResult();
static async Task MainAsync(string[] args)
{
_ApiHost.Start();
Console.WriteLine("Host started");
Console.ReadKey();
string jsonContent ="{\"OperationName\":null,\"Query\":\"query {\\r\\n\\t hero{\\r\\n\\t\\t name,\\r\\n\\t\\t id\\r\\n\\t }\\r\\n\\t human(id: \\\"1\\\"){\\r\\n\\r\\n homePlanet,\\r\\n name\\r\\n\\r\\n }\\r\\n }\",\"Variables\":null}";
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, new Uri("http://localhost:5000/"));
message.Content = new StringContent(jsonContent);
HttpResponseMessage result = await _Client.SendAsync(message);
string content = await result.Content.ReadAsStringAsync();
Console.WriteLine(content);
Console.ReadKey();
}
}
}
ApiHost.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace ApiTest
{
public class ApiHost
{
public HttpListener Listener = new HttpListener();
private bool _Stop;
public void Start()
{
Listener.Prefixes.Add("http://+:5000/");
Listener.Start();
Task.Run(() =>
{
Semaphore semaphore = new Semaphore(4, 4);
while (!_Stop)
{
semaphore.WaitOne();
Listener.GetContextAsync().ContinueWith(async (contextTask) =>
{
try
{
semaphore.Release();
HttpListenerContext context = await contextTask.ConfigureAwait(false);
Process(context);
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
});
}
});
}
private void Process(HttpListenerContext ctx)
{
try
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string text;
using (StreamReader reader = new StreamReader(ctx.Request.InputStream, ctx.Request.ContentEncoding))
{
text = reader.ReadToEnd();
}
stopwatch.Stop();
using (Stream output = ctx.Response.OutputStream)
{
using (StreamWriter writer = new StreamWriter(output) { AutoFlush = true })
{
writer.Write(text);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
Question:
Why do I have 360ms when using the internal library. When I use Insomnia for example I don't have this delay!
Kaspersky was the problem. After stopping the application it is running without any problems!

Sample Application on HttpClient with .NETCoreApp 1.1

I want to send a Http request to some website(URL) and get a response(Basically I need to use GetAsync and PutAsync methods for this) and I need to do it with.NETCoreApp 1.1 in VS2017.
Do get and post
Setting headers
Ignore TLS cert errors
Does anyone have a simple example how to achieve this?
I found this example in the API documentation HttpClient Class, but it is not clear how to achieve the above points.
I spend a couple of hours looking at the source code corefx and came up with this simple example
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CoreFxHttpClientHandlerTest
{
public class Program
{
private static void Main(string[] args)
{
}
public static async Task<bool> Run()
{
var ignoreTls = true;
using (var httpClientHandler = new HttpClientHandler())
{
if (ignoreTls)
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
}
using (var client = new HttpClient(httpClientHandler))
{
using (HttpResponseMessage response = await client.GetAsync("https://test.com/get"))
{
Console.WriteLine(response.StatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
using (var httpContent = new StringContent("{ \"id\": \"4\" }", Encoding.UTF8, "application/json"))
{
var request = new HttpRequestMessage(HttpMethod.Post, "http://test.com/api/users")
{
Content = httpContent
};
httpContent.Headers.Add("Cookie", "a:e");
using (HttpResponseMessage response = await client.SendAsync(request))
{
Console.WriteLine(response.StatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseContent);
}
}
}
}
return true;
}
}
}
See code in github.

How to Send a Remote Notification on a Button Click? Xamarin.Android C#

I need to send a GCM Notification On A button click in the android application made through xamarin.
I Have followed this tutorial https://developer.xamarin.com/guides/cross-platform/application_fundamentals/notifications/android/remote_notifications_in_android/
Button btnCLick = Findviewbyid<button>(resource.id.btnclikc);
btnCLick.Click += btnCLick_CLICK;
void btnCLick_Click (object sender, System.EventArgs e)
{
// Here i need to send my notification. I am not able to get it.
}
I Use a MessageSender.exe to send my notification but i cant make it into my application.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace MessageSender
{
class Program
{
public const string API_KEY = "API_KEY";
public const string MESSAGE = "MESSAGE";
static void Main(string[] args)
{
var jGcmData = new JObject();
var jData = new JObject();
jData.Add("message", MESSAGE);
jGcmData.Add("to", "/topics/global");
jGcmData.Add("data", jData);
var url = new Uri("https://gcm-http.googleapis.com/gcm/send");
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation(
"Authorization", "key=" + API_KEY);
Task.WaitAll(client.PostAsync(url,
new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
.ContinueWith(response =>
{
Console.WriteLine(response);
Console.WriteLine("Message sent: check the client device notification tray.");
}));
}
}
catch (Exception e)
{
Console.WriteLine("Unable to send GCM message:");
Console.Error.WriteLine(e.StackTrace);
}
}
}
}
I need to make this into my application button click in xamarin.Android
How Should i do that??
If I get your question right than your need a cross-platform HttpClient usage implementation for xamarin, right?
Try this: Consuming a RESTful Web Service. The topic might be a bit misleading but you should just get the HttpClient code you need.
async void MyNotificationPost(Uri uri, string json)
{
HttpClient client = new HttpClient();
var content = new StringContent (json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(uri, content);
...
if (response.IsSuccessStatusCode)
{
...
}
}
In this example, the crossplatform Microsoft HTTP Client Libraries are used. If you do not like that you can use the conventional HttpWebRequest which is available in stock.
Task<WebResponse> HTTPRequestSend(
Uri uri,
byte[] bodyData,
CancellationToken cancellationToken)
{
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.Method = "POST";
request.Headers["Accept"] = "application/json";
return Task.Factory.FromAsync<Stream>(
request.BeginGetRequestStream,
request.EndGetRequestStream,
null).ContinueWith(
reqStreamTask =>
{
using (reqStreamTask.Result)
{
reqStreamTask.Result.Write(bodyData, 0, bodyData.Length);
}
return Task.Factory.FromAsync<WebResponse>(
request.BeginGetResponse,
request.EndGetResponse,
null).ContinueWith(
resTask =>
{
return resTask.Result;
},
cancellationToken);
},
cancellationToken).Unwrap();
}
If you need that synchronous, be very careful not to get stuck in a deadlock. Do not forget to use ConfigureAwait(false) or the like.
P.S. I see you are using the ContinueWith and do not care for it's danger. Have a look here: ContinueWith is Dangerous, Too and do not miss the main article: StartNew is Dangerous
Actually I used the same as given in the question.
string API_KEY = "APIKEY";
var jGcmData = new JObject();
var jData = new JObject();
jData.Add("message", message);
jGcmData.Add("to", "/topics/global");
jGcmData.Add("data", jData);
var url = new Uri("https://gcm-http.googleapis.com/gcm/send");
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation(
"Authorization", "key=" + API_KEY);
Task.WaitAll(client.PostAsync(url,
new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
.ContinueWith(response =>
{
Console.WriteLine(response);
Console.WriteLine("Message sent: check the client device notification tray.");
}));
}
}
catch (Exception e)
{
Console.WriteLine("Unable to send GCM message:");
Console.Error.WriteLine(e.StackTrace);
}
It worked. Thanks for your Help. Brother #ZverevEugene

Categories

Resources