How to call POST method from API using HttpClient? - c#

I am trying to use the HttpClient class to call a POST method from my API which is supposed to add Server information to a DB.
The way I'm trying to call it is below. But when I step through it to debug it steps through my if statement for response.IsSuccessStatusCode.
public static async Task<Server> PostServer(Server server)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:50489/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent content = new StringContent(JsonConvert.SerializeObject(server));
// HTTP POST
HttpResponseMessage response = await client.PostAsync("api/Server/", content);
if (response.IsSuccessStatusCode)
{
string data = await response.Content.ReadAsStringAsync();
server = JsonConvert.DeserializeObject<Server>(data);
}
}
return server;
}
Also here is the POST method in my API below it was automatically generated in VS.
// POST: api/Servers
[ResponseType(typeof(Server))]
public async Task<IHttpActionResult> PostServer(Server server)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Servers.Add(server);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = server.Server_ID }, server);
}

Related

c# asp.net website calling a webApi

I meet a problem because of my inexperience managing Threads.
I have this Action bellow :
public static async Task<joueurs> loadjoueurs(int id)
{
joueurs EmpInfo = new joueurs();
using (var client = new HttpClient())
{
//Passing service base url
client.BaseAddress = new Uri("http://www.myWebApi.fr/api/");
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Sending request to find web api REST service resource GetAllEmployees using HttpClient
HttpResponseMessage Res = await client.GetAsync("joueurs?id=" + id);
//Checking the response is successful or not which is sent using HttpClient
if (Res.IsSuccessStatusCode)
{
//Storing the response details recieved from web api
var EmpResponse = Res.Content.ReadAsStringAsync().Result;
//Deserializing the response recieved from web api and storing into the Employee list
EmpInfo = JsonConvert.DeserializeObject<joueurs>(EmpResponse);
return EmpInfo;
}
return null;
}
it s just client to get my data from a webApi (no ssl no authentication, when I test it I receive the right values)
but when I make a call using the function above (in my asp.net website) .... it stay stucked at the HttpResponseMessage = await .... eternally.
In my webApi I have two functions same name but different parameters .
public async Task<IHttpActionResult> Getjoueur(int iduser, int idsport)
and
public async Task<IHttpActionResult> Getjoueur(int id)
So I am don't know where the problem comes from.
(sequel) Here is the place where I call the Task :
public SuperModel(int id)
{
this.joueur = Repojoueurs.loadjoueurs(id).Result;
/* this.classificationSport = Repoclassificationsport.loadclassificationsport().Result;
...
*/
}
And then my Supermodel is instantiated here in my Home controller :
public ActionResult Index(int id)
{
SuperModel superModel = new SuperModel(id);
return View(superModel);
}
Can you try not to use the async and wait. Around three changes like below
public static HttpResponseMessage loadjoueurs(int id)
{
HttpResponseMessage Res = client.GetAsync("joueurs?id=" + id);
return Request.CreateResponse(HttpStatusCode.OK,EmpInfo, "application/json");
}

WebAPI: using async methods in business logic

The aim is to make controller that uses async method in my custom service.
Controller:
[Route("api/data/summary")]
[HttpGet]
public async Task<IHttpActionResult> Get()
{
var result = await DataService.GetDataObjects();
return Ok(result);
}
Service:
public static async Task<IEnumerable<DataObject>> GetDataObjects()
{
var apiKey = "some-api-key";
var path = "path-to-external-service";
using (var client = new HttpClient())
{
var dataToProcess = // some data object
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
client.BaseAddress = new Uri(path);
HttpResponseMessage response = await client.PostAsJsonAsync("", dataToProcess);
var content = await response.Content.ReadAsStringAsync();
var result = MakeEntities(content); // some logic
return result;
}
}
But I came across with the problem that controller's action returns empty result before service actually finished processing data.
Could you please advice how to implement it correctly?
Your code is OK and controller doesn't seem to return a value before GetDataObjects returns value.
Except for the situations below:
MakeEntities uses some asynchronous operation and you don't await it inside MakeEntities. So MakeEntities return task.
Exception rises while your code is running. Make sure GetDataObjects and MakeEntities code works fine.
The aim is to make controller that uses async method in my custom service.
Controller:
[HttpGet]
[Route("api/data/summary")]
public async Task<IHttpActionResult> Get()
{
var result = await DataService.GetDataObjects().ConfigureAwait(false);
return Ok(result);
}
Service:
public static async Task<ResponseEntity> GetDataObjects()
{
ResponseEntity response = new ResponseEntity();
var apiKey = "some-api-key";
var path = "path-to-external-service";
using (var client = new HttpClient())
{
var dataToProcess = // some data object
client.BaseAddress = new Uri(path);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsJsonAsync("", dataToProcess).ConfigureAwait(false);
string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var result = JsonConvert.DeserializeObject<ResponseEntity>(responseString);
return response;
}
}

Using Cookies based authentication in WebAPI and asp.net core

Scenario:
I have a solution, in which, i have both WebAPI and Asp.Net Core MVC Project. I have implemented Cookies based authentication in WebAPI. It's working great while testing using Postman. But when i consume the WebAPI Service from my MVC project, authentication seems to be broken.
Here's my code:
WebAPI:
Startup.cs
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "ApiAuth",
AutomaticAuthenticate = true,
AutomaticChallenge = false
});
AccountController.cs
[HttpPost]
[Route("authenticate")]
public IActionResult Authenticate([FromBody]LoginModel login)
{
if (_accountManager.Authenticate(login))
{
var identity = new ClaimsIdentity("password");
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
HttpContext.Authentication.SignInAsync("ApiAuth", new ClaimsPrincipal(identity)).Wait();
}
else
{
return Unauthorized();
}
return Ok(_accountManager.Authenticate(login));
}
All Controllers have this attribute [Authorize(Roles = "User")]
MVC App:
AccountController.cs
public async Task<IActionResult> Login(LoginModel loginModel)
{
var loginFlag = false;
HttpResponseMessage response = await ServiceCall<LoginModel>.postData(URLPREFIX + "/authenticate", loginModel);
if (response.IsSuccessStatusCode)
{
loginFlag = await response.Content.ReadAsAsync<bool>();
}
if (loginFlag)
{
return RedirectToAction("Index", "Home");
}
else
{
return View();
}
}
ServiceCall.cs:
public static class ServiceCall<T>
{
static HttpClient client = new HttpClient();
const string HTTP_BASE = "http://localhost:13359/";
public static async Task<HttpResponseMessage> postData(string Url, T data)
{
HttpResponseMessage response = null;
StringContent content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
client.BaseAddress = new Uri(HTTP_BASE);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
response = await client.PostAsync(Url, content);
return response;
}
}
Here is my Screenshot:
The login function in both WebAPI and MVC is executing correctly, but when navigating to home page, i could not consume the service. Any Advice would be helpful. Thanks.
Update #1:
Here is my project repo with the issue. Please take a look. Thanks
i think problem is here:
HttpResponseMessage response = await ServiceCall<LoginModel>.postData(URLPREFIX + "/authenticate", loginModel);
if (response.IsSuccessStatusCode)
{
loginFlag = await response.Content.ReadAsAsync<bool>();
}
you are using a new request authenticate, this authenticate write a cookie in the response, of course not working on your real browser request.
you need using browser request the authenticate directly, let cookie write back to client, then your client can request home index.

Asp.net mvc web api async request result

I have a web api controller action that sends a request to another server and gets an image.
public class MyController : ApiController
{
public async Runner<HttpResponseMessage> Wms()
{
return await Run();
}
private Task<HttpResponseMessage> Run()
{
HttpRequestMessage requestMessage = new HttpRequestMessage();
requestMessage.RequestUri = "http://....";
foreach (var header in this.Request.Headers)
requestMessage.Headers.Add(header.Key, header.Value);
return requestMessage.SendAsync();
}
}
How can I get async request result of requestMessage.SendAsync()
You'll need to add the async modifier to the method and await SendAsync():
private async Task<HttpResponseMessage> RunAsync()
{
HttpRequestMessage requestMessage = new HttpRequestMessage();
requestMessage.RequestUri = "http://....";
foreach (var header in this.Request.Headers)
requestMessage.Headers.Add(header.Key, header.Value);
HttpResponseMessage response = await requestMessage.SendAsync();
string resultData = await response.Content.ReadAsStringAsync();
}
Or if you want the response inside Wms, you can await that.

How to return a new type from Web API post?

I'm trying to come up with a way to post to a Web API controller with one object but have a different, processed, object return. None of the methods I've been able to find have solved the issue.
Here's my method in my MVC project that posts to my Web API project
public dynamic PostStuff<X>(string action, X request)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var task = client.PostAsJsonAsync(new Uri("host/api/somecontroller/post, request);
task.Wait();
var response = task.Result;
return response;
}
}
This is my Web API controller code
public HttpResponseMessage Post([FromBody] FooObject foo)
{
var res = Request.CreateResponse(HttpStatusCode.OK,
new ValidationResponse<FooObject>
{
ID = new Random().Next(1000, 1000000),
Content =
new List<IContent>()
{
{
new Content()
{
Name = "TheContent",
Type = "SomeType",
Value = "This is some content for the page : " + foo.Bar
}
}
},
Product = new ProductFoo(),
Validated = true
});
return res;
}
}
When I put a break in my WebAPI controller code, the res variable is correctly created. Once the processing goes back to the PostStuff method, all I get is a StreamResponse with no trace of the ValidationResponse object created in the Web API controller. There are no errors but I can't use anything in the response beyond that the post succeeded. How can I extract the ValidationResponse from my posting method?
I have built myself this generic function as a helper for POSTing to Web API
Usage
var result = PostAsync<MyDataType, MyResultType>("http://...", MyData)
Function
public async Task<U> PostAsync<T, U>(string url, T model)
{
using (HttpClient httpClient = new HttpClient(httpHandler))
{
var result = await httpClient.PostAsJsonAsync<T>(url, model);
if (result.IsSuccessStatusCode == false)
{
string message = await result.Content.ReadAsStringAsync();
throw new Exception(message);
}
else
{
return await result.Content.ReadAsAsync<U>();
}
}
}
And HttpClientHandler configured for Windows Auth
protected HttpClientHandler httpHandler = new HttpClientHandler() { PreAuthenticate = true, UseDefaultCredentials = true };

Categories