I have the following Code in Visual Studio
using System;
using System.Windows.Forms;
using System.Net.Http;
using System.Web;
using System.Net;
using System.IO;
namespace Xml_Trial
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void LoadUrl_click(object sender, EventArgs e)
{
Xmlcheck(TxtUrl.Text);
}
private static async void Xmlcheck(string TxtUrl)
{
try
{
HttpClient client = new HttpClient() ; //httpclient
var request = new HttpRequestMessage(HttpMethod.Get, TxtUrl);
HttpResponseMessage response = await client.GetAsync(request.RequestUri);
if (response.StatusCode == HttpStatusCode.OK)
{
// Console.WriteLine((int)response.StatusCode); More code here
}
response.Dispose();
}
catch (HttpRequestException e)
{
MessageBox.Show(e.Message);
}
}
}
}
I have written the code this way to get the 200 status code Console.WriteLine((int)response.StatusCode)
What Code is else posssible to get more out of the httpstatuscode description rather than just "OK" or "200"....
I believe you're looking for the ReasonPhrase property, which is "the reason phrase which typically is sent by servers together with the status code."
For example:
Console.WriteLine($"{(int)response.StatusCode} {response.ReasonPhrase}");
A list of all valid status codes (including my favourite, 418) with their default reason phrases is here: HTTP response status codes
Related
I want to post a request to a url, using content-type and authorization. I am getting error 400 "Bad Request". I have tested with the same data and headers in python and it worked.
So I think there is something wrong with how I set up my headers. But I haven't found a workaround.
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Http.Headers;
using System.Net.Http;
namespace PostRequests
{
//var data={"bio":"cheesy"}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static readonly HttpClient client = new HttpClient();
private void go_Click(object sender, EventArgs e)
{
var values = new Dictionary<string, string>
{
{"bio", "test"}
};
sendPost("https://discord.com/api/v9/users/#me", values);
}
async void sendPost(string url, Dictionary<string, string> vals)
{
string authValue = "mytoken";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authValue);
var content = new FormUrlEncodedContent(vals);
var request = new HttpRequestMessage(new HttpMethod("PATCH"), url) { Content = content };
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.SendAsync(request);
}
}
}
I have the following code:
<ContentPage.BindingContext>
<local:PisterosViewModel/>
</ContentPage.BindingContext>
<Picker x:Name="pck_Pisteros"
ItemDisplayBinding="{Binding PisteroN}"
ItemsSource="{Binding PisterosLista}"
SelectedItem="{Binding PisterosLista}"
Title="Seleccione el usuario..."/>
Then my Model:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.Contracts;
using System.Text;
namespace ServLottery.Models
{
public class Pisteros
{
public string PisteroID { get; set; }
public string PisteroN { get; set; }
}
}
and the view model:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace ServLottery.Models
{
public class PisterosViewModel
{
public IList<Pisteros> PisterosLista { get; set; }
public PisterosViewModel()
{
try
{
PisterosLista = new ObservableCollection<Pisteros>();
GetPisteros();
}
catch (Exception ex)
{
throw ex;
}
}
private async void GetPisteros()
{
try
{
RestClient client = new RestClient();
var pist = await client.Get<Models.Pisteros>("https://servicentroapi.azurewebsites.net/api/Pisteros");
if (pist != null)
{
PisterosLista = pist;
}
}
catch (Exception ex)
{
throw ex;
}
}
}
}
I set an breakpoint in var pist and it does have the values, then Pisteros list seems to get the values too, and this is executed when the page load, so I don't understand what's the problem, but the picker never shows the options.
Welcome to SO !
It seems like BindingContext in Xaml can not deal with the dynamical data ,such API data from web server .
There is a workaround binding ItemSource dynamically by using coding in ContentPage , also can refer to this officail sample .
Therefore , adding code in Page.Xaml.cs as follow :
protected override async void OnAppearing()
{
pck_Pisteros.ItemsSource = await GetTasksAsync();
base.OnAppearing();
}
private async Task<List<Pisteros>> GetTasksAsync()
{
List<Pisteros> PisterosLista = new List<Pisteros>();
HttpClient client = new HttpClient();
Uri uri = new Uri(string.Format("https://servicentroapi.azurewebsites.net/api/Pisteros", string.Empty));
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
PisterosLista = JsonConvert.DeserializeObject<List<Pisteros>>(content);
Console.WriteLine("content :: " + content);
Console.WriteLine("Data :: " + PisterosLista);
}
return PisterosLista;
}
Now it will show:
So I am building out a custom content negotiation formatter like this for a custom data format that we need to use in our .NET Core API.
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using CustomFormatterDemo.Models;
using Microsoft.Net.Http.Headers;
using System.Reflection;
using Microsoft.Extensions.Logging;
namespace CustomFormatterDemo.Formatters
{
#region classdef
public class VcardOutputFormatter : TextOutputFormatter
#endregion
{
#region ctor
public VcardOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
#endregion
#region canwritetype
protected override bool CanWriteType(Type type)
{
if (typeof(Contact).IsAssignableFrom(type)
|| typeof(IEnumerable<Contact>).IsAssignableFrom(type))
{
return base.CanWriteType(type);
}
return false;
}
#endregion
#region writeresponse
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
IServiceProvider serviceProvider = context.HttpContext.RequestServices;
var logger = serviceProvider.GetService(typeof(ILogger<VcardOutputFormatter>)) as ILogger;
var response = context.HttpContext.Response;
var buffer = new StringBuilder();
if (context.Object is IEnumerable<Contact>)
{
foreach (Contact contact in context.Object as IEnumerable<Contact>)
{
FormatVcard(buffer, contact, logger);
}
}
else
{
var contact = context.Object as Contact;
FormatVcard(buffer, contact, logger);
}
await response.WriteAsync(buffer.ToString());
}
private static void FormatVcard(StringBuilder buffer, Contact contact, ILogger logger)
{
buffer.AppendLine("BEGIN:VCARD");
buffer.AppendLine("VERSION:2.1");
buffer.AppendFormat($"N:{contact.LastName};{contact.FirstName}\r\n");
buffer.AppendFormat($"FN:{contact.FirstName} {contact.LastName}\r\n");
buffer.AppendFormat($"UID:{contact.ID}\r\n");
buffer.AppendLine("END:VCARD");
logger.LogInformation("Writing {FirstName} {LastName}", contact.FirstName, contact.LastName);
}
#endregion
}
}
Obviously, I can just do something like throw new Exception("this doesn't work"), but that is just going to give the API consumer a 500 response. Curious how I can throw more graceful errors with particular codes or, at the very least, the error details for the 500 status.
The HttpResponse class has a StatusCode property, so you can just set that. Then you can set the body to an error message of some sort if you'd like.
The status code should probably reflect what's wrong. So if the request just had bad data, you could return 400 Bad Request:
context.HttpContext.Response.StatusCode = 400;
Hi i have a Api that i want to use to collect data from a backend that spits out json i need to get this via C# Application and it's http functionalities. My question is should i use a rest api and setup an async thread that downloads the data and then use the data as i want to from there or should i somehow use something close to a Web Api i have an authentication that is required to exist in a header. This has given me some hedaches because i keep on being split by what to use for what. I mean i need to do a Httprequest with a header. this i later on need to use for posting to another database. but the user of the program should not have to see the data itself. i have two examples that i have done but i don't know with what i should continue? this is my two examples in code...
Example 1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
namespace Plugin
{
public enum HttpVerb
{
GET,
POST,
PUT,
DELETE
}
class Api
{
private HttpVerb HttpMethod { get; set; }
public Api()
{}
public string startDownload()
{
return (Download("sending token"));
}
private string Download(string token)
{
string strResponseValue = string.Empty;
string finnishedOutput = string.Empty;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("Url");
request.Headers.Add("Authorization", "Bearer " + token);
request.Method = HttpMethod.ToString();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
strResponseValue = reader.ReadToEnd();
}
return strResponseValue;
}
catch (WebException e)
{
HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
if ((int)httpResponse.StatusCode == 401)
{}
int errorCodeInt;
string errorCode;
errorCodeInt = (int)httpResponse.StatusCode;
errorCode = errorCodeInt.ToString();
return errorCode;
}
}
}
}
Example 2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TestAPi
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Api.InitializeClient("");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
namespace TestAPi
{
public class Api
{
private static HttpClient ApiClient { get; set;}
private string url { get; set;}
public static void InitializeClient(string token)
{
ApiClient = new HttpClient();
ApiClient.BaseAddress = new Uri("your url");
ApiClient.DefaultRequestHeaders.Accept.Clear();
ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("Bearer Authentication"));
}
public async Task<Data> LoadData()
{
url = ApiClient.BaseAddress.ToString();
using (HttpResponseMessage response = await ApiClient.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
Data data = await response.Content.ReadAsAsync<data>();
return data;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
}
}
}
I'm trying to do a webrequest from my C# Windows application to my website,
but the desired result is empty or null when called only from C# but not from website where it works as expected.
Before I do my request, I need to begin with a login request which works as expected and does indeed return the correct value.
IMPORTANT EDIT:
I tried to copypaste my PHP code in to my login.php file and it does work in C# and returns the correct count-value.
Is my HttpClient not properly configured maybe?
My PHP test code looks as following:
<?php
session_start();
if(!isset($_SESSION['user'])){ header("Location: index.php"); }
include_once 'dbconnect.php'; //contains $db
$sql = "SELECT * FROM myTable"; //contains two rows
$sql_res = mysqli_query($db, $sql);
$proxyCount = mysqli_num_rows($sql_res);
$echo "Count: ".$proxyCount;
?>
And my C# looks like this:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net.Http;
using ModernHttpClient;
using Newtonsoft.Json;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void log(string str)
{
logbox.AppendText(str + Environment.NewLine);
}
private string host = "http://www.mywebsite.com/";
private HttpClient httpClient = new HttpClient(new NativeMessageHandler());
private async Task<string> request(string target, Dictionary<string, string> _parameters)
{
string uri = host + target;
using (HttpResponseMessage response = await httpClient.PostAsync(uri, new FormUrlEncodedContent(_parameters)))
return new StreamReader(await response.Content.ReadAsStreamAsync()).ReadToEnd();
}
private async void button1_Click(object sender, EventArgs e)
{
string loginResp = await request("login.php", new Dictionary<string, string> { { "username", "user" }, { "password", "password" } });
log(loginResp);
}
private async void button2_Click(object sender, EventArgs e)
{
string proxiesResp = await request("proxy/proxy.php", new Dictionary<string, string> { { "getAllProxyRequests", "" } });
//above returns "count: " in C#, but returns "count: 2" in webbrowser
log(proxiesResp);
}
}
}
Found the problem, it was human error.
I had the file dbconnect.php located one directory below where myProblem.php was located.
I had to change the line saying
include_once 'dbconnect.php';
to
include_once '../dbconnect.php';