I have to code a little C# Console application (but my knowledge on .NET is almost NULL) to make a POST request to a PHP API, for which I'm using an HttpClient instance. The API accepts a JSON like this
{
"User": {
"email": "email#host.com",
"password": "something"
},
"Establishment": {
"id": 147
}
}
After doing some research on how to do this what I've done so far is this:
static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://italdelo.web.development.co/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// HTTP POST
Dictionary<string, string> user = new Dictionary<string, string>();
Dictionary<string, int> establishment = new Dictionary<string, int>();
HashTable postdata = new HashTable();
user.Add("email","email#host.com");
user.Add("password","something");
establishment.Add("id",147);
postdata.Add("User",user);
postdata.Add("Establishment",establishment);
HttpResponseMessage response = await client.PostAsJsonAsync("apiname/service", postdata);
response.EnsureSuccessStatusCode(); // Throw if not a success code.
}
catch (HttpRequestException e)
{
Console.WriteLine("Exception details: " + e.ToString());
}
}
}
Running this code I got this error message:
Severity Code Description Project File Line Suppression State Error CS0246 The type or namespace name 'HashTable' could not be found (are you missing a using directive or an assembly reference?) ProjectName C:\Users\...\Program.cs 47 Active
I know the error is the way I'm trying to setup the JSON to send to the API, which is a hashtable containing values (hashtable's key-value notation) as dictionaries. I'm pretty sure this is dumb but I don't really know how to setup this JSON for the API, I have no choice, I need to use C#. Can you help me please giving me some advice on how to fix this or get this done in another way? Thanks in advance.
you can create a class that will serve as parameter for consuming API.
//you classes
public class Parameter
{
public User user { get; set;}
public Establishment {get; set;}
}
public class User
{
public string email {get; set;}
public string password {get; set}
}
public class Establishment
{
public int id {get;set;}
}
//in your api calling method:
`var p = new Parameter
{
Establishment = new Establishment
{
id = 123
},
User = new User
{
email = "email",
password = "password"
}
};
HttpResponseMessage response = await client.PostAsJsonAsync("apiname/service", p);
Use c# anonymous classes
var payload = new{
User=new {
email= "email#host.com",
password= "something"
},
Establishment=new {
id= 147
}
}
then use newtonsoft json.net
var json = JsonConvert.SerializeObject(payload);
Looks like a typo, C# Hashtable does not capitalize the middle T:
https://msdn.microsoft.com/en-us/library/system.collections.hashtable(v=vs.110).aspx
Related
I am pretty new to C# and want to create a REST Get request with Basic auth.
I'm using RestSharp but i can't find a proper working full example.
This is my code:
using RestSharp;
using RestSharp.Authenticators;
namespace HttpClientAPP
{
class Program
{
static void Main(string[] args)
{
var client = new RestClient("https://data.myhost.de");
client.Authenticator = new HttpBasicAuthenticator("user", "xxxx");
var request = new RestRequest("resource",Method.Get);
client.ExecuteGetAsync(request).Wait();
Console.WriteLine("as");
}
}
}
This is thejson answer I expect and i want to parse it to use the data to store it in a MYSQL DB:
{"info": [
{
"method": "GET",
"url": "https://data.myhost.de/zfa-values/{zfaId}",
"description": "Get a ZFA value by id"
},
{
"method": "GET",
"url": "https://data.myhost.de/zfa-values",
"description": "Get a list of available ZFA values"
},
{
"method": "GET",
"url": "https://data.myhost.de/new-zfa-values",
"description": "Get a list of available ZFA values which have not been viewed yet"
},
{
"method": "GET",
"url": "https://data.myhost.de/",
"description": "Get a list of api endpoints"
}
]}
How do I parse the json response?
At https://restsharp.dev/v107/#recommended-usage there is some guidance (but at time of writing this answer I think it might have a typo)
Get docs says:
public class GitHubClient {
readonly RestClient _client;
public GitHubClient() {
_client = new RestClient("https://api.github.com/")
.AddDefaultHeader(KnownHeaders.Accept, "application/vnd.github.v3+json");
}
public Task<GitHubRepo[]> GetRepos()
=> _client.GetAsync<GitHubRepo[]>("users/aspnet/repos");
^^^^^^^^
//note: I think this should be GetJsonAsync
}
Post docs says:
var request = new MyRequest { Data = "foo" };
var response = await _client.PostAsync<MyRequest, MyResponse>(request, cancellationToken);
^^^^^^^^^ ^^^^^^^
//note: i think this should be PostJsonAsync and the first arg should be a string url path
You have classes that represent the json you send/get back, and RestSharp will de/serialize them for you. If you want some help making classes from JSON, take a look at services like http://app.QuickType.io - you paste your json and you get representative classes. The online generators are usually a bit more sophisticated in terms of what they interpret/the attributes they decorate with. Pasting your json into QT gives (you can choose a better name than SomeRoot):
namespace SomeNamespace
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class SomeRoot
{
[JsonProperty("info")]
public Info[] Info { get; set; }
}
public partial class Info
{
[JsonProperty("method")]
public string Method { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
}
public partial class SomeRoot
{
public static SomeRoot FromJson(string json) => JsonConvert.DeserializeObject<SomeRoot>(json, SomeNamespace.Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this SomeRoot self) => JsonConvert.SerializeObject(self, SomeNamespace.Converter.Settings);
}
internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
}
And use like:
using RestSharp;
using RestSharp.Authenticators;
namespace HttpClientAPP
{
class Program
{
static async Task Main(string[] args)
{
var client = new RestClient("https://data.myhost.de");
client.Authenticator = new HttpBasicAuthenticator("user", "xxxx");
var res = await client.GetJsonAsync<SomeRoot>("");
Console.ReadLine(); //prevent exit
}
}
}
First, you can use newtosoft json nuget package:
Docs: https://www.newtonsoft.com/json
Example:
class ApiEndpoint{
public string Method {get;set;} // or you can use enum
public string Url {get;set;}
public string Description {get;set;}
}
// some logic
public void Fetch()
{
var client = new RestClient("https://data.myhost.de");
client.Authenticator = new HttpBasicAuthenticator("user", "xxxx");
var request = new RestRequest("resource",Method.Get);
var response = client.Get(request);
// read response as json
var json = JsonConvert.DeserializeObject<ICollection<ApiEndpoint>>(response);
// now json will have structure in your example
}
Other way is to add swagger gen for you server, get openapi.json and then generate sharp client using nswag
https://blog.logrocket.com/generate-typescript-csharp-clients-nswag-api/
Hi I am using following code to add a record to Zoho Creator form using asp.net c#.
However I receive in respose "The form has been removed from publish."
I have checked form at Zoho creator its working fine & has been published.
Please help me figure out the problem.
public partial class WebForm1 : System.Web.UI.Page
{
protected void btnSubmit_OnClick(object sender, EventArgs e)
{
var response = Http.Post("https://creator.zoho.com/saadelboury1/myfirstApp/form-perma/NEWDISTRIBUTOR/record/add/", new NameValueCollection() {
{ "authtoken", "<KEY>" },
{ "scope", "creatorapi" },
{ "First_Name", "John" },
{ "Last_Name", "Doe" },
{ "Email", "someone22#gmail.com" },
});
string result = System.Text.Encoding.UTF8.GetString(response);
Response.Write(result);
}
}
}
public static class Http
{
public static byte[] Post(string uri, NameValueCollection pairs)
{
byte[] response = null;
using (WebClient client = new WebClient())
{
response = client.UploadValues(uri, pairs);
}
return response;
}
Turned out, the url I was calling was wrong.
The correct url format is:
https://creator.zoho.com/api/[username]/xml/[application_name]/form/[form_name]/record/add/
Here I push the records from the school form to the student form with the help of add record task.
var = Insert into Student
[
Name = input.Name
Email = input.Email
Phone = input.Phone
Address = input. Address
];
Variable holding the ID of the new record.
<<form_link_name> Link name of the field for which the value is specified.
Value to be assigned to the field. You can directly specify a value, or you can specify an expression.
Okay I have limited understanding of working with API's
Im trying to get to grips with Adobe Sign API and hit a dead end, on there test page i have enterd this and it works
But i have no idea on how then do that in C#
I have tried the following, but know its missing the OAuth stuff and I'm just not sure what to try next.
by the way foo.GetAgreementCreationInfo() just gets the string that is in the screen shot, I just moved it out cus it was big and ugly
var foo = new Models();
var client = new RestClient("https://api.na1.echosign.com/api/rest/v5");
// client.Authenticator = new HttpBasicAuthenticator(username, password);
var request = new RestRequest("agreements/{AgreementCreationInfo}", Method.POST);
request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
request.AddUrlSegment("AgreementCreationInfo", foo.GetAgreementCreationInfo()); // replaces matching token in request.Resource
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
You are misinterpreting the API documentation. The Access-Token parameter needed in your API is clearly an HTTP header, while the AgreementCreationInfo is simply the request body in JSON format. There is no URI segment, so rewrite your code as follows:
var foo = new Models();
//populate foo
var client = new RestClient("https://api.na1.echosign.com/api/rest/v5");
var request = new RestRequest("agreements", Method.POST);
request.AddHeader("Access-Token", "access_token_here!");
// request.AddHeader("x-api-user", "userid:jondoe"); //if you want to add the second header
request.AddParameter("application/json", foo.GetAgreementCreationInfo(), ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
var content = response.Content;
Please also be aware that in RESTSharp you do not need to manually serialize your body into JSON at all. If you create a strongly typed object (or just an anonymous object could be enough) that has the same structure of your final JSON, RESTSharp will serialize it for you.
For a better approach I strongly suggest you to replace this line:
request.AddParameter("application/json", foo.GetAgreementCreationInfo(), ParameterType.RequestBody);
With those:
request.RequestFormat = DataFormat.Json;
request.AddBody(foo);
Assuming your foo object is of type Models and has the following structure along with its properties:
public class Models
{
public DocumentCreationInfo documentCreationInfo { get; set; }
}
public class DocumentCreationInfo
{
public List<FileInfo> fileInfos { get; set; }
public string name { get; set; }
public List<RecipientSetInfo> recipientSetInfos { get; set; }
public string signatureType { get; set; }
public string signatureFlow { get; set; }
}
public class FileInfo
{
public string transientDocumentId { get; set; }
}
public class RecipientSetInfo
{
public List<RecipientSetMemberInfo> recipientSetMemberInfos { get; set; }
public string recipientSetRole { get; set; }
}
public class RecipientSetMemberInfo
{
public string email { get; set; }
public string fax { get; set; }
}
Link to AdobeSign Repository:
ADOBE SIGN SDK C# SHARP API Ver. 6
Adobe Sign API integrators - this is kind of hidden away in AdobeSigns GIT repositories. The link to all the generated SWAGGER classes (models/methods) for C# and REST client integrated C# project in a GIT project you can compile and use right inside your project as a project reference or compiled DLL. This project has been updated to use version 6 of the API. This was a huge time saver for me. I have provided a quick example below on how to use it. I hope this helps others save time as well.
Note you might have to switch out BasePath in the configuration.cs so you can retrieve the initial Adobe URI "BaseURI" call if you get 404 error.
Change BasePath = "http://localhost/api/rest/v6";
To:
BasePath = "https://api.echosign.com/api/rest/v6";
//include namespaces:
using IO.Swagger.Api;
using IO.Swagger.model.agreements;
using IO.Swagger.model.baseUris;
using IO.Swagger.model.transientDocuments;
using System.IO;
Then this quick minimal demonstrates BaseUri, Upload PDF a.k.a. Transient Document, then Create Agreement (Example 1 Basic Signer Minimal Options)
string transientDocumentId = "";
string adobesignDocKey = "";
string baseURI = "";
var apiInstanceBase = new BaseUrisApi();
var authorization = "Bearer " + apiKey; //Example as Integration Key, see adobesign docs For OAuth.
try
{
//___________________GET BASEURI ADOBE SIGN_________________________
BaseUriInfo resultBase = apiInstanceBase.GetBaseUris(authorization);
baseURI = resultBase.ApiAccessPoint; //return base uri
//___________________UPLOAD YOUR PDF THEN REF ADOBE SIGN_________________________
var apiInstanceFileUpload = new TransientDocumentsApi(baseURI + "api/rest/v6/");
TransientDocumentResponse resultTransientID = apiInstanceFileUpload.CreateTransientDocument(authorization, File.OpenRead([ENTER YOUR LOCAL FILE PATH]), null, null, _filename, null);
if (!String.IsNullOrEmpty(resultTransientID.TransientDocumentId))
{
transientDocumentId = resultTransientID.TransientDocumentId; //returns the transient doc id to use below as reference
}
var apiInstance = new AgreementsApi(baseURI + "api/rest/v6/");
//___________________CREATE ADOBE SIGN_________________________
var agreementId = ""; // string | The agreement identifier, as returned by the agreement creation API or retrieved from the API to fetch agreements.
var agreementInfo = new AgreementCreationInfo();
//transientDocument, libraryDocument or a URL (note the full namespace/conflicts with System.IO
List<IO.Swagger.model.agreements.FileInfo> useFile = new List<IO.Swagger.model.agreements.FileInfo>();
useFile.Add(new IO.Swagger.model.agreements.FileInfo { TransientDocumentId = transientDocumentId });
agreementInfo.FileInfos = useFile;
//Add Email To Send To:
List<ParticipantSetMemberInfo> partSigners = new List<ParticipantSetMemberInfo>();
partSigners.Add( new ParticipantSetMemberInfo { Email = "[ENTER VALID EMAIL SIGNER]", SecurityOption=null });
//Add Signer To Participant
List<ParticipantSetInfo> partSetInfo = new List<ParticipantSetInfo>();
partSetInfo.Add(new ParticipantSetInfo { Name = "signer1", MemberInfos = partSigners, Role = ParticipantSetInfo.RoleEnum.SIGNER, Order=1, Label="" });
agreementInfo.ParticipantSetsInfo = partSetInfo;
agreementInfo.SignatureType = AgreementCreationInfo.SignatureTypeEnum.ESIGN;
agreementInfo.Name = "Example Esign For API";
agreementInfo.Message = "Some sample Message To Use Signing";
agreementInfo.State = AgreementCreationInfo.StateEnum.INPROCESS;
AgreementCreationResponse result = apiInstance.CreateAgreement(authorization, agreementInfo, null, null);
adobesignDocKey = result.Id; //returns the document Id to reference later to get status/info on GET
}
catch (Exception ex)
{
//Capture and write errors to debug or display to user
System.Diagnostics.Debug.Write(ex.Message.ToString());
}
I am trying to create a JSON object in a .Net 5 application. The default options I am presented with are Microsoft.AspNet.Mvc.Formatters.Json, Microsoft.Extensions.Configuration.Json, and Newtonsoft.Json when I use the Visual Studio 2015 Qucik Actions on Json. My understanding is that Configuration.Json is for reading form the appsettings.json so it probably is not what I would use to create a JSON object. I can't find any real information on Formatters.Json, how to use it, or what it's intended use it. Newtonsoft.Json is will documented but is it better over the Formatters.Json? Which of the two should I be using?
Taken directly from ASP.NET Core 1 tests
var expected = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { foo = "abcd" }));
Also taken from the tests and slightly modified, call it with HttpClient to see how to send your json string to the server.
var response = await Client.PostAsync(
"http://localhost/api/ActionUsingSpecificFormatters",
new StringContent(yourJsonContent, Encoding.UTF8, "application/json"));
As per Newtonsoft you can simply encode, then do whatever you want after that.
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "ExpiryDate": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JsonConvert.DeserializeObject(output);
Putting it all together - I just tested this. Keep in mind this is a real generic pass through test from MVC 6 (ASP.NET 5 ie ASP.NET Core 1) :)
[HttpGet]
public async Task<string> Get()
{
var client = new HttpClient();
var customer = new Customer() { Name = "Schmo", Address = "1999 Purple Rain St" };
var customerJson = JsonConvert.SerializeObject(customer);
var response = await client.PostAsync(
"http://localhost:4815/api/Customer",
new StringContent(customerJson, Encoding.UTF8, "application/json"));
//just some template output to test which I'm getting back.
string resultJson = "{ 'Name':'adam'}";
if (response.StatusCode == HttpStatusCode.OK)
{
resultJson = await response.Content.ReadAsStringAsync();
var updatedCustomer = JsonConvert.DeserializeObject(resultJson);
}
return resultJson;
}
public class Customer
{
public string Name { get; set; }
public string Address { get; set; }
}
I would use Json.Net to create the JSON payloads for sure (Afterall, Microsoft does for Web Api).
Nuget Package Source:
Install-Package Newtonsoft.Json
Here is an example. If you want to call a REST api that returns a product when you make a GET call then you might do something like this.
public static class Main
{
string url = "https://TheDomainYouWantToContact.com/products/1";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json";
request.Accept = "application/json";
var httpResponse = (HttpWebResponse)request.GetResponse();
var dataStream = httpResponse.GetResponseStream();
var reader = new StreamReader(dataStream);
var responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
// This is the code that turns the JSON string into the Product object.
Product productFromServer = JsonConvert.Deserialize<Product>(responseFromServer);
Console.Writeline(productFromServer.Id);
}
// This is the class that represents the JSON that you want to post to the service.
public class Product
{
public string Id { get; set; }
public decimal Cost { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The exact same method can be used for POST and PUT as well.
You can use 3rd party assemblies to make this super easy too. We are the authors of DynamicApis.Api
Install-Package DynamicApis.Api
The code to make the same request using this client would be:
public static class Main
{
RestClient client = new RestClient();
string url = "https://YourDomain.com/products/1";
var productFromServer = client.Get<Product>(url);
Console.Writeline(productFromServer.Id);
}
you should use NewtonSoft.Json if you need to serialize objects as json
You shouldn't have to do anything special to send back Json data. The default output formatter is already Json, and if your Startup.cs file is somewhat normal, you should have a line similar to this:
services.AddMvc();
By default, this already contains the Json formatter, and your controller should autonegotiate the return type based on what the browser asked. So a controller like the following should work (taken from this Github issue, which contains some information on why/how this work):
public class ValuesController : ApiController
{
public SomeClass Get()
{
return new SomeClass();
}
public SomeClass Post([FromBody] SomeClass x)
{
return x;
}
}
Im trying to convert a C# example thats posting to a API into .vb.
My programming skills are limited so I cant seem to get it to work.
One problem is that I cant use httpclient cause the project is in Framework 3.5 and thats something I cant change. Anyone?
Here is the c# code:
public class TriggerData
{
//if true, the contact will be updated with sent property data (affects performance).
public bool saveProps { get; set; }
public string originalId { get; set; }
public Dictionary<string, string> properties { get; set; }
public TriggerData()
{
properties = new Dictionary<string, string>();
}
}
public class CarmaTriggerClient
{
static void Main(string[] args)
{
//use your settings here
var host = "https://www.adress.com";
var customerId = 0;
var triggerId = 0;
var user = "";
var pass = "";
var data = new TriggerData();
//unique identifier in the list
data.originalId = "th#post.se";
///property keys are emailAddress, mobileNumber, firstName, lastName, city, zip, country, middleName, title, dateOfBirth, sex, or the id of one of your custom properties
data.properties["emailAddress"] = "th#post.se";
data.properties["4321"] = "some data";
//REST resource for trigger
var path = string.Format("/rest/{0}/triggers/{1}/messages", customerId, triggerId);
TriggerAsync(host, path, user, pass, data).Wait();
}
static async Task TriggerAsync(string host, string path, string user, string pass, TriggerData data)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(host);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var credentials = string.Format("{0}:{1}", user, pass);
//http://www.ietf.org/rfc/rfc2617.txt
var authorization = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(credentials));
client.DefaultRequestHeaders.Add("Authorization", "Basic " + authorization);
// HTTP POST
var response = await client.PostAsJsonAsync(path, data);
if (!response.IsSuccessStatusCode)
{
System.Diagnostics.Debug.WriteLine(response.Content);
}
}
}
}
}
Search for csharp vbnet online converter and you will find, for example, http://www.carlosag.net/tools/codetranslator/
I checked your code. It does translate.
Framework versions are the same regarding vbnet and csharp; which is another question.
HTH