I'm currently trying to post an angular model to a web API inside .NET Core MVC. The model on the Angular side is populated correctly before the point at which is Posts to the web API. When it reaches the API, however, the model looks like {"urlEndpoint":null,"token":null}.
I have tried changing the header Content-Type, I have tried adding [FromBody], I have also tried changing the controller from HttpResponseMessage to IHttpActionResult - pretty much every solution on stack overflow to similar problems actually. However, the interesting thing is, that this same code works in an older project on standard .NET.
Any help with this would be massively appreciated... it's driving me nuts!
Angular component:
getPdfData() {
let token = this.httpService.getToken("token");
this.urlAndTokenModel = new UrlAndTokenModel();
this.urlAndTokenModel.Token = token;
this.urlAndTokenModel.UrlEndpoint = this.apiEndpoint;
this.httpService.postPdfBytes('/blahblah/api/pleaseworkthistime', this.urlAndTokenModel, this.successCallback.bind(this),
this.failureCallback.bind(this));
}
Angular http.service
postPdfBytes(url: string, data: UrlAndTokenModel, successCallback, errorCallback) {
return this.http.post(url, data,
{
headers: new HttpHeaders().set('Content-Type', 'application/json'),
responseType: 'blob'
}
).subscribe(
resp => successCallback(resp),
error => errorCallback(error)
);
}
Web API:
public class TestController : BaseController
{
public TestController(ICacheHelper cacheHelper) :
base(cacheHelper)
{
}
[Route("api/pleaseworkthistime")]
[HttpPost]
public HttpResponseMessage GetDocument(UrlAndTokenModel data)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", data.Token);
var responseTask = client.GetAsync(data.UrlEndpoint);
responseTask.Wait();
var result = responseTask.Result;
byte[] finalResult = null;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsByteArrayAsync();
readTask.Wait();
finalResult = readTask.Result;
}
var httpRequestMessage = new HttpRequestMessage();
var httpResponseMessage = httpRequestMessage.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new ByteArrayContent(finalResult);
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = "mytestpdf.pdf";
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
}
}
Then obviously there is the angular URLAndTokenModel with a URLEndpoint and a Token - the same is mirrored in the C# model.
Finally solved it! I hope this helps anyone else going through the same issue.
When it posts to the .NET API, it firstly needs to be JSON.Stringify
this.httpService.postPdfBytes('/blahblah/api/pleaseworkthistime', JSON.stringify(this.urlAndTokenModel), this.successCallback.bind(this),
this.failureCallback.bind(this));
The angular http.service also needs to be updated therefore to a string instead of a model.
postPdfBytes(url: string, data: string, successCallback, errorCallback)
at this point it still wasn't having it, and then a simple add of [FromBody] to the Controller and walahh!
public HttpResponseMessage GetDocument([FromBody] UrlAndTokenModel data)
Related
I'm writing a simple dotnet core API, under search controller which like below :
[HttpGet("order")]
public async Task <Order> SearchOrder(string ordername, int siteid) {
return await service.getorder(ordername,siteid)
}
The swagger UI where the path https://devehost/search/order test pretty work, but when I use another client to call this api by below
client = new HttpClient {
BaseAddress = new Uri("https://devehost")
};
var request = new HttpRequestMessage(HttpMethod.Get, "Search/order") {
Content = new FormUrlEncodedContent(
new List<KeyValuePair<string, string>> {
new("ordername", "pizza-1"),
new("siteid", "1"),
})
};
var response = await client.SendAsync(request);
The status code always return bad request. But the postman is work, can I know the problem inside?
Thank you
For a GET request, the parameters should be sent in the querystring, not the request body.
GET - HTTP | MDN
Note: Sending body/payload in a GET request may cause some existing implementations to reject the request — while not prohibited by the specification, the semantics are undefined.
For .NET Core, you can use the Microsoft.AspNetCore.WebUtilities.QueryHelpers class to append the parameters to the URL:
Dictionary<string, string> parameters = new()
{
["ordername"] = "pizza-1",
["siteid"] = "1",
};
string url = QueryHelpers.AppendQueryString("Search/order", parameters);
using var request = new HttpRequestMessage(HttpMethod.Get, url);
using var response = await client.SendAsync(request);
I'm trying to pass xml file to api using RestSharp, but I'm receiving the file at the Post method as null.
Here is my code:
public void SendXmlToApi()
{
var client = new RestClient(_uri);
var request = new RestRequest(Method.POST);
request.AddFile("Xml",XmlPath);
request.RequestFormat = DataFormat.Xml;
request.AddHeader("content-type", "application/xml");
var response = client.Execute(request);
bool res = (response.StatusCode == HttpStatusCode.OK);
}
And my Post Func:
[HttpPost]
[Route("Test")]
public void UpdateResult(XDocument a)
{
}
Any idea whats the problem?
I don't use XML, so this deviates a little from your example, but it is a viable option for posting XML into a [HttpPost] API endpoint. I used your SendXmlToApi() example untouched (just supplied my own _uri and XmpPath variables) and was successful (Core 3.1).
I modified your receiving code to be:
[HttpPost]
[Route("test")]
public async Task UpdateResult()
{
string body = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
XDocument xdoc = XDocument.Parse(body);
}
Of course, you'll want to put guard rails on this and have proper error handling and validation, but it should get you over the hump.
I'm quite noob into asp.net
I'm building a simple solution in VS2019, using asp.net MVC, which is supposed to send a User data to another API which will be responsible for saving into database.
So far, both APIs are REST and I'm not using core
Basically, it is a form with a submit that will POST to the external project, pretty simple.
I'm following some tutorials and stuff but there are so many different ways that got me confused, so I decided to ask here
Here's what I have so far
[HttpPost]
public async ActionResult Index(User user)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://pathtoAPI.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
User newuser = new User()
{
email = user.email,
nome = user.nome,
cpf = user.cpf,
cnpj = user.cnpj,
userName = user.userName,
senha = user.senha,
telefone = user.telefone
};
var jsonContent = JsonConvert.SerializeObject(newuser);
var contentString = new StringContent(jsonContent, Encoding.UTF8, "application/json");
contentString.Headers.ContentType = new
MediaTypeHeaderValue("application/json");
//contentString.Headers.Add("Session-Token", session_token);
HttpResponseMessage response = await client.PostAsync("register", contentString);
return Content($"{response}");
}
I want to receive the "OK" message from the other API and just print it on my screen, I'm using the cshtml file to handle the front and the form as well.
The return though seems to be wrong, it's expecting either 'null, task, task, or something like.
Can someone please help me with this code?
Thanks
You need to return the content of the response, not the response object itself.
HttpResponseMessage response = await client.PostAsync("register", contentString);
string responseBody = await response.Content.ReadAsStringAsync();
return Content(responseBody);
I try to send request with serialized data to my server using HttpClient
var content = JsonConvert.SerializeObject(note);
var response = await _client.PostAsync(url, new StringContent(content));
here my method in controller:
[HttpPost]
public ActionResult<Note>Create([FromBody]note)
{
_noteService.Create(note);
return new Note();//CreatedAtRoute("GetBook", new { id = note.Id.ToString() }, note);
}
and i get error Unsupported MediaType, i tried to change parameter "note" datatype to StringContent and i get "Bad Gateway" error, i tried to change it to String data type and it is empty.
How i can get data sending from xamarin application on my server ?
Edited:
Probably i have to get serialized string and deserialize it to my object.
Solved, please check solution below
Xamarin Code:
var content = JsonConvert.SerializeObject(note);
var response = await _client.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"));
.Net Core WebApi Code:
[HttpPost]
public ActionResult<Note>Create(Note note)
{
_noteService.Create(note);
return CreatedAtRoute("GetNote", new { id = note.Id.ToString() }, note);
}
I am creating prototype of application where in I am trying to send data in request header and body from C# MVC Controller and also created web api project Post action to process the request.
My code goes like this::
MVC Project code to Post Request:
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
VM VM = new VM();
VM.Name = " TEST Name";
VM.Address = " TEST Address ";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:58297");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("username","test");
var json = JsonConvert.SerializeObject(VM);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var result1 = await client.PostAsync("api/Values/Post", content);
}
return View();
}
}
My code in WEB API project :
// POST api/values
public IHttpActionResult Post([FromBody]API.VM vm)
{
try
{
HttpRequestMessage re = new HttpRequestMessage();
StreamWriter sw = new StreamWriter(#"E:\Apple\txt.log", false);
var headers = re.Headers;
string token = "";
if (headers.Contains("username"))
{
token = headers.GetValues("username").First();
}
sw.WriteLine("From header" + token);
sw.WriteLine("From BODY" + vm.Name);
sw.WriteLine("From BODY" + vm.Address);
sw.WriteLine("Line2");
sw.Close();
return Ok("Success");
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
What I have understood is [FromBody]API.VM vm gets data from Http request body which means vm object is getting data from HTTP Request body.I am able to get request body. I am not able to understand how do I pass data in header from MVC controller (I want to pass JSON Data) and retrieve data in WEB Api post method?
I have used client.DefaultRequestHeaders.Add("username","test"); in MVC project to pass header data and
HttpRequestMessage re = new HttpRequestMessage();
var headers = re.Headers;
string token = "";
if (headers.Contains("username"))
{
token = headers.GetValues("username").First();
}
in WEB API project to get data but I am not able to get username value.
In order to get your data via headers, you would need to enable CORS: Install-Package Microsoft.AspNet.WebApi.Cors in your project and then in your Register method under WebApiConfig.cs, add this line: EnableCors();.
Once done, you can access your header variable as:
IEnumerable<string> values = new List<string>();
actionContext.Request.Headers.TryGetValues("username", out values);
You can get all headers being passed to a method of a web API using below lines inside that web API method:
HttpActionContext actionContext = this.ActionContext;
var headers = actionContext.Request.Headers;