Use C# HttpWebRequest to send json data to web service - c#

I am trying to send http request of json data to a web service. It successfully get directed to the web service but the data is always null...
Here is my web service:
public bool CheckUserExist ([FromBody] string Email)
{
List<User> all_users = repo.getUsers();
var match = all_users.Find(i => i.Email == Email);
if (match == null)
{
return false;
}
else
{
return true;
}
}
and here is my Http Request:
var webAddr = "http://localhost:59305/api/User/CheckUserExist";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"Email\":\"Email\"}";
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return RedirectToAction("Index");
}
as i mentioned...Iam using a debugger at the web service function...the request get directed to the service but variable "Email" is always null

The quick fix is to change what you are posting. If you want your API endpoint to work with [FromBody] string Email, then you should change your "json":
string json = "\"a#b.c\"";
streamWriter.Write(json);
streamWriter.Flush();
However, you may want to consider a few other changes for the long term on your approach:
Let your repo return IQueryable instead of List or some other IEnumerable. As written, you will always return every user from the database. With Linq, you can leverage the lazy initialization and let your query only get the matching user instead of get EVERY user and then find the match. This will not scale well.
Use new HttpClient and async functionality in your action instead of HttpWebRequest
Instead of manually building your JSON, let .NET do the work and create a class that gets serialized
With the above solutions in place (except for first since you didn't post your data context, didn't want to make too many assumptions), here are some examples to get you started:
Define a shared user search class (shared either in same project or shared DLL)
public class UserSearch
{
public string Email { get; set; }
}
Let Web API map post against the search class
public bool CheckUserExist([FromBody] UserSearch userSearch)
{
IQueryable<User> all_users = repo.getUsers();
var isMatch = all_users.Any(i => i.Email == userSearch.Email);
return isMatch;
}
Change to HttpClient and use async to send API request with new search class
public async Task<ActionResult> Check()
{
using (var client = new HttpClient())
{
var search = new UserSearch() { Email = "a#b.c" };
var response = await client.PostAsJsonAsync("http://localhost:59305/api/User/CheckUserExist", search);
if (response.IsSuccessStatusCode)
{
bool exists = await response.Content.ReadAsAsync<bool>();
// Handle what to do with exists
return RedirectToAction("Index");
}
else
{
// Handle unsuccessful call
throw new Exception("Application error");
}
}
}

You can't use string to accept the post data, please define a struct class or use dynamic to receive the Json string.

Related

Unable to get child value on newtonsoft.Json.LinqJvalue when reading coinbase api?

Hello I am trying to get the coinbase API exchange rates from the URL however json.net does not seem to be able to format the JSON file to read the children
this is the method that throws the error
public string CalculateCoinValue(Coinbase connector)
{
//bool valid = connector.rates.isValid;
string cryptoExchangeRate;
if (connector.rates != null)
{
cryptoExchangeRate = (string)connector.rates["data"]["currency"]["rates"][Settings.defualtCrypto.ToUpper()];
}
return "";
}
this is the method im using to get the JSON data which stores it in a JObject whithin the Coinbase class
public async Task<JObject> GetExchangeRatesAsync()
{
HttpClient webClient = new HttpClient();
string url = string.Format("https://api.coinbase.com/v2/exchange-rates?currency=" + Settings.defaultCurrency);
HttpResponseMessage coinbaseJsonRaw = await webClient.GetAsync(url);
return JObject.Parse(await coinbaseJsonRaw.Content.ReadAsStringAsync());
}
what am I doing wrong for this not to work?
The json returned looks different. try the below
cryptoExchangeRate = (string)connector["data"]["rates"][Settings.defualtCrypto.ToUpper()];

Retrieve data from API call response?

I'm working on an application to get some API experience with C#. I'm pulling data from a site involving jokes, but no matter what I try I can't seem to get the actual response.
I've gone over several different methods, this is the farthest I've gotten. I'm using the RestSharp library, and it's returning RestSharp.RestResponse. I've tried several different methods of deserializing this as that's what I believe is needed. From the API I'm using, the default response format is text/html. Any tips on extracting this to a string containing the joke itself would be most appreciated.
public void CreateJoke()
{
var client = new RestClient("https://icanhazdadjoke.com/");
client.AddDefaultHeader("user-agent", "Dadbot");
var request = new RestRequest("https://icanhazdadjoke.com/");
var response = client.Get(request);
lblJoke.Text = response.ToString();
}
Expected result: getting a string I can put into a label. Actual result: RestSharp.RestResponse.
Try instead accessing the Content property of response:
public void CreateJoke()
{
var client = new RestClient("https://icanhazdadjoke.com/");
client.AddDefaultHeader("user-agent", "Dadbot");
var request = new RestRequest("https://icanhazdadjoke.com/");
var response = client.Get(request);
lblJoke.Text = response.Content;
}
Hopefully that helps!
I guess this is what you want.
public string CreateJoke()
{
var request = (HttpWebRequest)WebRequest.Create("https://icanhazdadjoke.com/");
request.Method = "GET";
request.Accept = "text/plain";
var jokeResponse = request.GetResponse();
var joke = string.Empty;
using (var sr = new StreamReader(jokeResponse.GetResponseStream()))
{
joke = sr.ReadToEnd();
}
//Console.WriteLine(joke);
return joke;
}

Disable ModelBinder in .NetCore

HeyGuys
I'm working on a WebApi project that receives requests from clients and redirects these requests to other services that are not open for direct access.
By default, .Net serializes and deserializes the Json request parameters automatically, so I need to re-serialize them before calling the appropriate service. The same problem occurs when receiving the service response. I need to deserialize it before sending the response to the user; otherwise .Net framework will serialize it one more time, resulting in a "Json of Json" response.
I found this answer but it does not seem to work with .NetCore; so I tried to create my own ModelBinder that just reads the Json object and returns it.
class JsonUnformatterBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
return new JsonUnformatterBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));
}
}
and
class JsonUnformatterBinder : IModelBinder
{
private readonly IModelBinder _fallbackBinder;
public JsonUnformatterBinder(IModelBinder fallbackBinder)
{
_fallbackBinder = fallbackBinder;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
string currMethod = bindingContext.ActionContext.HttpContext.Request.Method;
if ("POST".Equals(currMethod) || "PUT".Equals(currMethod))
{
string strData = new StreamReader(bindingContext.ActionContext.HttpContext.Request.Body).ReadToEnd();
bindingContext.Result = ModelBindingResult.Success(strData);
return Task.CompletedTask;
}
return _fallbackBinder.BindModelAsync(bindingContext);
}
}
This code is very simple, it was my first attempt and it worked well for my purposes. However, I still get the "Json of Json" problem when I take the second service answer and returns back to the user.
I basically have no idea what I can do to overcome this, so any workaround is welcome here.
If you need just redirect a request without modification, you could read it from input stream directly and send it to inner service. You could also use such approach to read responce from inner service.
//1. Set empty parameter list in action then neither serializator nor model binder are not invoked.
public async Task<ContentResult> ProxyAction(/*empty parameter list*/)
{
var newUrl = #"https://stackoverflow.com";
var data = this.Request.Body;
using (var client = new HttpClient())
{
//2. Read request body from input stream.
var reader = new StreamReader(data);
var json = reader.ReadToEnd();
using (var content = new StringContent(json))
{
//3. Set correct content type
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(this.Request.ContentType);
//4. Post request to inner service
var response = await client.PostAsync(newUrl, content);
//5. Read response without deserialization
var innerResponse = await response.Content.ReadAsStringAsync();
var contentType = response.Content.Headers.ContentType.ToString();
var statusCode = response.StatusCode;
//6. Return inner response without serialization
var outerResponse = this.Content(innerResponse, contentType);
outerResponse.StatusCode = (int)statusCode;
return outerResponse;
}
}
}

calling rest api on client side c#

I am new to api stuff.
I want to get the result of this api(http://services.groupkt.com/country/get/all) in c# code. can you help me by suggesting any code and tutorial as well. thanks
i have tried this code but it doesnot work.
public async Task DownloadData()
{
string url = string.Format("http://services.groupkt.com/country/get/all");
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
var jsonString = await client.GetStringAsync(url);
JToken token = JToken.Parse(jsonString);
foreach (var item in token)
{
txtarea.Value= item.ToString();
}
}
First of all use
client.GetStringAsync(url).Result
instead of
client.GetStringAsync(url)
Second after you received the json, it becomes very simple to parse the result. I saw the previous answeres and they were all using a loop, which is not a good idea in my opinion to parse.
Use Newtonsoft.Json library and its very handy in such situations. I've parsed your json response using this library.
Make a class of result, i.e.
public class result
{
public string name { get; set; }
public string alpha3_code { get; set; }
public string alpha2_code { get; set; }
}
put this code after getting json response for parsing your json.
JObject jsonResponse = JObject.Parse(jsonString);
JObject objResponse = (JObject)jsonResponse["RestResponse"];
Dictionary<string, JArray> _Data = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, JArray>>(objResponse.ToString());
var results = _Data["result"].ToObject<List<result>>();
It works perfectly, I've tested this.
Don't forget to add Newtonsoft.Json AND Newtonsoft.Json.Linq namespaces
Your code fetches the response correctly. But parsing incorrectly.
Try the below full parsing code.
public async Task DownloadData()
{
string url = string.Format("http://services.groupkt.com/country/get/all");
string top_parent_key_name = "RestResponse";
string second_parent_key_name = "result";
string field_one_key_name = "name";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
var jsonString = await client.GetStringAsync(url);
JToken token = JToken.Parse(jsonString);
foreach (var item in token[top_parent_key_name][second_parent_key_name])
{
txtarea.InnerText = item[field_one_key_name].ToString();
}
}
Just to add, I would prefer dynamics here so the code communicates more clearly.
public async Task DownloadData()
{
string url = $"http://services.groupkt.com/country/get/all";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
string response = await client.GetStringAsync(url);
dynamic json = JToken.Parse(response);
foreach (var item in token.RestResponse.result)
{
//Note: Your over writing the text here for each item you pass
// Did you mean to concat instead? += "\n\r" + item.name;
txtarea.InnerText = item.ToString();
}
}
Now as for just doing txtarea.InnerText = ... in a question you labeled with "ASP.NET-Web-Api" seems a bit odd, is it an ASP.NET MVC with Web Api or a more classic Web Forms application?

how to have Web Api send Json.net Serialized string object back to client Correctly?

I am serializing an IEnumerbale object using JsonConvert.SerializeObject( );
it produces string with quotes and escape character with spaces
from web Api controller i return that string using code below
[HttpGet]
public string GetDegreeCodes(int id)
{
string result = //output from JsonConvert.SerializeObject( );
return result;
}
"[{\"DegreeId\":1,\"DegreeName\":\"High School\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get High School
Degree\r\"},{\"DegreeId\":2,\"DegreeName\":\"Associate\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Associate
Degree\r\"},{\"DegreeId\":3,\"DegreeName\":\"Bachelor\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Bachelor
Degree\r\"},{\"DegreeId\":4,\"DegreeName\":\"Masters\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Master
Degree\r\"},{\"DegreeId\":5,\"DegreeName\":\"Doctrate\",\"ImageSrc\":\"
http://bootsnipp.com/apple-touch-icon-114x114-pre\",\"Description\":\"
Get Doctorate Degree\"}]"
This is my ajax and it does not recognize the JSON correctly because of the extra wrapper quotes and escape characters,
$.ajax({
url: "/api/helloservice/getdegreecodes",
type: "get",
contentType: "application/text",
data: { id: 1 }
}).done(function (data) {
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
viewEduModel.degreeCodes.push(data[i]);
}
}
});
i need to use JsonConvert.SerializeObject since i am caching it as a JSon
in my redis cache server using booksleeve that way I do not need to
re serialize and read from db every time. how do i avoid web api controller sending
Quotes and backslashes? i could simply return IEnumerable and
let Web Api do the JSOn serialization but i need to cache it on redis
side
You could something like below:
[HttpGet]
public HttpResponseMessage GetDegreeCodes(int id)
{
StringContent sc = new StringContent("Your JSON content from Redis here");
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = new HttpResponseMessage();
resp.Content = sc;
return resp;
}
by using this you can call your webapi through code.
using (var client = new WebClient()) //WebClient
{
string mystring = "";
client.Headers.Add("Content-Type:application/json"); //Content-Type
client.Headers.Add("Accept:application/json");
var dataa = Encoding.UTF8.GetBytes("{\"Username\":\"sdfsd\"}");
byte[] a = client.UploadData("your API url", "POST",dataa);
myString = Encoding.UTF8.GetString(a);
}

Categories