Unable to send form data to web api using postasync - c#

I am trying to send sourceFile value to web api. But in API i am receiving is null
var formVars = new Dictionary<string, string>();
formVars.Add("sourceFile", "Helloo");
HttpContent content = new FormUrlEncodedContent(formVars);
var result = client.PostAsync("ImageApi/Compare", content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
return Content(resultContent);
API code
[HttpPost()]
public ActionResult Compare(string sourceFile)
{
return Ok(sourceFile);
}
I am using DotNet core 2.0

you need to await the result, do not try to access .Result yourself. The call would not have completed at that point.
you need to use something like this:
HttpContent content = new FormUrlEncodedContent(formVars);
var result = await client.PostAsync("ImageApi/Compare", content);
result .EnsureSuccessStatusCode();
string responseBody = await result.Content.ReadAsStringAsync();
This is based on your code and hasn't been tested but should set you on the right path to get this working. Don't ever try to do async stuff by accessing .Result.
One more thing, you need to use a model as well.
create a model class, which has all the properties you add in your dictionary.
in your case it will be something like :
public class MyModel{
public string sourceFile { get ;set; }
}
your controller becomes:
[HttpPost()]
public ActionResult Compare([FromBody]MyModel model)
{
return Ok(model.sourceFile);
}

Related

C# - Get dynamic URL Parameter on API call

I'm building an movie API using C# where the user calls my endpoint and based on the id passed, my server calls the movie db api to get some details.
For example: if a user calls the "/movie/id" endpoint, the server gets that id and pass it to the movieDb.Get method.
My main issue is on retrieving that id the user passes in the url when accessing my endpoint
This is what i've been trying:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/movie/{id}", (id) =>
{
object response = movieDb.Get($"/movie/{id}");
return response;
});
and my class:
public class MovieDB{
public async Task<object> Get(string uri){
try{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync($"{baseUrl}/{uri}?
{apiKey}");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
catch (Exception){
throw;
}
}
}
When i access "http://localhost:port/movie/616037", i expect to see the movie db return to this movie, but i get "conecction was recused by the localhost".
If i force and id like
string id = "616037"
and then call this method sending the correct endpoint on movie DB API, then it returns this movie details
e.g.
movieDB.Get($"/movie/{id}")
You need to specify parameter. Because without specifying id is HttpContext
Your code must look like this
app.MapGet("/movie/{id}", (int id) =>{
...
}

.NET Core 3.1 WebApi - Passthrough JSON response from another WebApi

I have the following setup:
WebApi #1 - Returns JSON via an OkResult class
WebApi #2 - Returns JSON via an OkResult class
WebApi #2 needs to call WebApi #1 and simply pass the JSON result back via its OkResult. The issue I have is if I do that, I end up with escaped JSON in the response:
"{\"id\":1,\"key\":\"value\",\"key\":\"value\",\"key\":\"value\",\"key\":\"value\"}"
What is the best way to just passthrough this return?
UPDATE:
Here is the code that makes the API call to WebApi #1:
public async Task<string> Get(string uri)
{
try
{
string responseBody = await _client.GetStringAsync(uri);
return responseBody;
}
catch (HttpRequestException ex)
{
_logger.LogError(ex.Message);
return null;
}
}
And here is the return in WebApi #2:
public async Task<IActionResult> Get(string data)
{
var uri = String.Format(Environment.GetEnvironmentVariable("ENDPOINT"), data);
var result = await _client.Get(uri);
return Ok(result);
}
You need to do this:
return Content(result, "application/json");

Passing values from controller to WebAPI

I have a need to track emails and pages on our website. We want to use a WebAPI for this, however I am very new and the examples I found were hard to follow. Here is my problem:
I have an EmailTrackerContoller with code like below:
public class EmailTrackingController : Controller
{
[OutputCache(NoStore = true , Duration = 0)]
[HttpPost]
public ActionResult GetPixel(string email, Guid emailID) {
var client = new HttpClient();
var endpoint = "http://localhost:2640/api/EmailTracker/SaveEmail"; --path to my API
var response = await client.PostAsync(endpoint, null); --this does not work
const string clearGif1X1 = "R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
return new FileContentResult(Convert.FromBase64String(clearGif1X1) , "image/gif");
}
}
I have also created a WebAPI that has a HttpPost Method Called SaveEmail:
[HttpPost]
public HttpResponseMessage SaveEmail([FromBody]string value) { --How do I get the Email and Guid I need from here?
var a = new DL.EmailTracking();
a.Insert("<email>" , Guid.NewGuid());
return Request.CreateResponse(HttpStatusCode.Accepted , "");
}
Couple of questions on this:
How do you pass values from the controller to the WebApi?
Any easy to follow examples would be great, of if you have a link that would be useful as well.
The second parameter of PostAsync is the content of the call.
Serialize the object as JSON that contains the values you want and add it as the content.
var obj = new { Email = "mail#mail.com" };
HttpStringContent msg = new HttpStringContent(JsonConvert.SerializeObject(obj));
var response = await client.PostAsync(endpoint, msg);
Modify the receiving method to receive the desired properties. I'd use a class as the methods parameter but you can use [FromBody] with all the properties listed as well.
public HttpResponseMessage SaveEmail(EmailSave model)

IHttpActionResult with JSON string

I have a method that originally returned an HttpResponseMessage and I'd like to convert this to return IHttpActionResult.
My problem is the current code is using JSON.Net to serialize a complex generic tree structure, which it does well using a custom JsonConverter I wrote (the code is working fine).
Here's what it returns:
string json = NodeToJson(personNode);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
The NodeToJson method is where the custom converter comes into play ...
private static string NodeToJson(Node<Person> personNode) {
var settings = new JsonSerializerSettings {
Converters = new List<JsonConverter> { new OrgChartConverter() },
Formatting = Formatting.Indented
};
return JsonConvert.SerializeObject(personNode, settings);
}
Note this returns a string, formatted as JSON.
If I switch this to IHttpActionResult, it seems to fail regardless of what I try. I can just leave it (it works) but I am supposed to be using best practices for this and IHttpActionResult seems to be what I should be using.
I have tried to return Json(json); but this results in invalid, unparsable JSON, presumably because it's trying to do a double conversion?
return Ok(json); results in the JSON string being wrapped in XML.
What is the right way to do this?
EDIT:
I have successfully converted every method in this project to use IHttpActionResult now except this particular method.
It's a serialization of a generic tree to JSON. Regardless of what approach I try, I get back invalid JSON. The HttpResponseMsessage approach works fine, but I can not get valid JSON back with IHttpActionResult.
You can create your own IHttpActionResult class instance to return the JSON and a method in your controller or base controller class to utilize it.
Create the IHttpActionResult instance that sets the content and status code:
public class JsonTextActionResult : IHttpActionResult
{
public HttpRequestMessage Request { get; }
public string JsonText { get; }
public JsonTextActionResult(HttpRequestMessage request, string jsonText)
{
Request = request;
JsonText = jsonText;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
public HttpResponseMessage Execute()
{
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(JsonText, Encoding.UTF8, "application/json");
return response;
}
}
Add a method to your controller to create the result. Here is a Web API example:
public class MyApiController : ApiController
{
protected internal virtual JsonTextActionResult JsonText(string jsonText)
{
return new JsonTextActionResult(Request, jsonText);
}
[HttpGet]
public IHttpActionResult GetJson()
{
string json = GetSomeJsonText();
return JsonText(json);
}
}
Another recommendation is as below;
var json = JToken.FromObject(yourObject);
return Ok(json);
I've got the same problem and this piece of code worked for me (Using Newtonsoft.Json nuget package to deserialize the json):
var unserializedContent = JsonConvert.DeserializeObject(json);
return Json(unserializedContent);
It seems we must have an object in order to Json() work as it should.
Some of the solutions here are converting string to JSON, that's not necessary.
You are just using computer resources for nothing.
// Instead of
// return Ok(jsonstring);
// do:
HttpResponseMessage response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jsonstring, Encoding.UTF8, "application/json");
Request.RegisterForDispose(response); //To avoid the Pragma CA2000 warning
return ResponseMessage(response);
Another solution At client side
You can make a small change to be prepared to receive a string and convert it if necessary. The code bellow is Javascript
var data;
if (typeof weapiresponse == "string")
data = JSON.parse(weapiresponse);
else
data = weapiresponse;
If you have no intention of using XML as a return type, you can also remove the XmlFormatter in your WebApiConfig:
config.Formatters.Remove(config.Formatters.XmlFormatter);
The correct way is to return:
Ok(json);
It's converting the result to XML because that's the default accepted return type. Try adding:
Accept: application/json into your API request headers, I think that should resolve the issue.
I had the same problem with web-service returning JSON string in a XML-tag. I tried all the simple solutions Like :
return Json(text) , json deserialize and adding config.Formatter for json, but that did't help. I got double cotes around the json object or it was malformed.
Only the solution written by TGRA worked for me.
create your own IHttpActionResult class instance to return the JSON
For me, the only way to return an IHttpActionResult with the string content as Json in the following.
[HttpGet]
public IHttpActionResult ReturnStringAsJson()
{
return this.ResponseMessage(new HttpResponseMessage
{
Content = new StringContent("[json string]"),
Encoding.UTF8,
"application/json"),
});
}

WebApi force action to return xml

I have this action:
public IHttpActionResult SearchFor(int aboItemType, DTO.FilterColumns filter)
{
//Do stuff...
return Ok<DataSet>(ds);
}
My client does:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
var response = client.PostAsJsonAsync(myurl).Result;
if (response.IsSuccessStatusCode)
{
var results = HttpUtility.HtmlDecode(response.Content.ReadAsStringAsync().Result);
}
The above scenario works perfectly. However, if I comment the Accept line, the action returns the dataset in json format.
I would like to force this one particular action to always send the result in xml. Is this possible? Maybe with an attribute?
I used Сonfiguration.Formatters.XmlFormatter
public IHttpActionResult Get()
{
...
return Content(HttpStatusCode.OK, Model, Configuration.Formatters.XmlFormatter);
}
Also you can do this (in the case you have to pass some http header values):
public IHttpActionResult Get()
{
var result = Request.CreateResponse(HttpStatusCode.OK,
model,
Configuration.Formatters.XmlFormatter);
result.Headers.Add("Access-Control-Allow-Origin", "*");
return ResponseMessage(result);
}

Categories