Web API Post Body Properties null - c#

I'm posting over a message from an Angular application and every time the post body is always coming into the function as null. A console log in the Angular application directly before the post request confirmed that the object did contain information, it seems to get lost somewhere along the way through.
public class SentMessage
{
public string MessageFrom { get; set; }
public string MessageTo { get; set; }
public string Message { get; set; }
}
// Post a new message
[Route("Conversation/AddTo")]
[HttpPost]
public IHttpActionResult AddToConversation(SentMessage message)
{
if (message is null)
{
return NotFound();
}
return Ok("Message Sent");
}
So far I've tried with and without [FromBody] on the method property as suggested in other posts, but past that I'm not sure what's going wrong.
........

Put [FromBody] on the method argument, as you've said, and make sure you're POSTing with the Content-Type of application/json.

Just modify the code
public IHttpActionResult AddToConversation([FromBody]SentMessage message)
{
if (message is null)
{
return NotFound();
}
return Ok("Message Sent");
}

Related

How can I catch missing or empty parameters passed into my Web API method?

I have this simple Net Core Web API HttpPut method to update an object called BakeCookieRecipe.
It works fine if the user passes in an id and BakeCookieRecipe object,
but if someone usint the API forgets to pass in the id and/or an empty BakeCookieRecipe object, the browser throws a 404 error.
I guess that's fine, but I also want to log the event with my logger.
But for some reason, I can't catch when the id and/or BakeCookieRecipe is either missing or empty.
Here is my code. You can see where I am trying to test the id and bakeCookieRecipe object that is passed in and log it.
But it never does. It also never sends the NotFound message I define.
Is there anything I can change to help me?
Thanks!
HttpPut("{id}")]
public async Task<IActionResult> PutBakeCookieRecipe(string id, BakeCookieRecipe bakeCookieRecipe)
{
if (string.IsNullOrWhiteSpace(id) || id != bakeCookieRecipe.BakeId)
{
Message = "id is missing or not found";
_logger.LogError(Message);
return NotFound("Id missing.");
}
if (!IsGuid(bakeCookieRecipe.CookieRecipeId.ToString()) || bakeCookieRecipe.CookieRecipeId == Guid.Empty)
{
Message = "RecipeId is missing";
_logger.LogWarning(Message);
return NotFound("RecipeId is missing or not found.");
}
_context.Entry(bakeCookieRecipe).State = EntityState.Modified;
await _context.SaveChangesAsync();
return NoContent();
}
// test to make sure a value is a Guid
private bool IsGuid(string value)
{
Guid x;
return Guid.TryParse(value, out x);
}
The problem causes using a new "smart" feature of Net6 that demands that all properties should be marked as nullable. And probably you are using API controller attribute. In this case an error is generated before in gets inside of the action. This is why you can't catch it.
So if you have problem only here you can change the action
HttpPut("{id?}")]
public async Task<IActionResult> PutBakeCookieRecipe(string id, BakeCookieRecipe? bakeCookieRecipe)
search this site, especially my answers, how to to get rid of this error forever.
If you wanna cath the parameters values, just remove an [ApiController] attribute for testing
I can't catch when the id and/or BakeCookieRecipe is either missing or
empty.
By default, you would get 400 error directly without getting into the method In webapi projects
You could try remove the ApiController and Route attribute and remove the parameter in the constructor of HttpPut attribute
[HttpPut]
public async Task<IActionResult> PutBakeCookieRecipe(string id, BakeCookieRecipe bakeCookieRecipe)
{
........
return NoContent();
}
Resgit the route in middleware as below:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "RouteName", pattern: "Api/{controller}/{action}/{id?}");
});
Result:
You can set your fields in the dto to [Required] and also use try catch to catch the error message .
Below is a simple code to this Hope this helps
DTO:
public class BakeCookieRecipe
{
[Required]
public Guid CookieRecipeId { get; set; }
[Required]
public Guid BakeId { get; set; }
[Required]
public string BakeName { get; set;}
}
Put Method:
[HttpPut("Bake")]
public async Task<IActionResult> Put(Guid id, BakeCookieRecipe b)
{
try
{
var user = await _context.bakeCookies.FirstOrDefaultAsync(x => x.CookieRecipeId == id);
if (user == null)
{
return NotFound();
}user.BakeName = b.BakeName; ;
user.BakeId = b.BakeId;
user.CookieRecipeId= b.CookieRecipeId;
await _context.SaveChangesAsync();
return NoContent();
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}[![Here ive attached the image of the resulting webapi][1]][1]

What's the correct structure for a HTTP Post method? ASP.NET Core Web API

I'm working on a simple notes api, I'm trying to create a Put method to update a note in my notes list, but when I try to update any note through the SwaggerUI I get a the 404 status code. I think that I'm missing something in the structure.
This is my [HttpPut] request:
[HttpPut("{id}")]
public IActionResult Put([FromBody] Note requestParam)
{
if (!ModelState.IsValid)
{
return BadRequest("Not a valid model");
}
using (_datacontext)
{
var ExistingNote = _datacontext.Note.Where(n => n.Id == requestParam.Id)
.FirstOrDefault<Note>();
if (ExistingNote != null)
{
ExistingNote.Title = requestParam.Title;
ExistingNote.Description = requestParam.Description;
ExistingNote.Completed = requestParam.Completed;
_datacontext.SaveChanges();
} else
{
return NotFound();
}
}
return Ok();
}
My DataContext:
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> option) : base(option)
{
}
public DbSet<Note> Note { get; set; }
}
And lastly my Note Model:
public class Note
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public bool Completed { get; set; }
}
After looking for different examples I haven't found a standard approach so I'm not sure what to do about it
I've researched about Http bodies since it seemed like it needed to be part of the request but still get the error code. What could be wrong with it? (Both post and get methods work!).
Also, the error code:
When using the [HttpPut("{id}")] attribute on your controller, you need to add a parameter to the controller method's signature:
IActionResult Put([FromRoute] int Id, [FromBody] Note requestParam)
You can then call the API like this when Id=123
PUT http://{base-url}/123
Then you need to query the data context using the id from the route (which means you can remove it from the body)
On the other hand, if you don't want the Id as part of the request URL and keep it in the body, you need to remove the Id from the route template:
[HttpPut] without {id}.
Needless to say, make sure the Id actually exists in the data context. Otherwise your code will return, yes, a 404.

How to respond based on received action in Web API 2 ASP.NET

How would I create one controller with one API link in Web API 2 ASP.NET to respond on received data by an action that is in that data?
For example I receive this data:
{"t":"868efd5a8917350b63dfe1bd64","action":"getExternalServicePar","args":
{"id":"4247f835bb59b80"}}
and now I need to respond based on this "action" value. If there is some other action value like "incrementVallet" I need to respond with different data, and all that from one API link, etc.
The obvious question to ask is "Why would you want to do that?". Why not multiple methods or even multiple controllers? Having said that, you could do the following if you really want to:
public class ActionDetails
{
public string t { get; set; }
public string action { get; set; }
public ArgsContainer args { get; set; }
}
public ArgsContainer
{
public string id { get; set; }
}
Controller and method:
public class MyController : ApiController
{
// POST is not really the right choice for operations that only GET something
// but if you want to pass an object as parameter you really don't have much of a choice
[HttpPost]
public HttpResponseMessage DoSomeAction(ActionDetails details)
{
// prepare the result content
string jsonResult = "{}";
switch (details.action)
{
case "getExternalServicePar":
var action1Result = GetFromSomewhere(details.args.id); // do something
jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(action1Result);
break;
case "incrementVallet":
var action2Result = ...; // do something else
jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(action2Result);
break;
}
// put the serialized object into the response (and hope the client knows what to do with it)
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jsonResult, Encoding.UTF8, "application/json");
return response;
}
}

Web API POST object always null

I'm new with ASP.NET Web API's and I'm trying to write an API method that will send emails.
This is my sendEmail controller:
[Route("sendemail")]
[HttpPost]
public bool SendEmail(EmailObj email)
{
var To = email.sendTo;
var Subject = email.subject;
var Message = email.message;
...
}
However, whenever I test it using postman, the object sent is null.
This is how my json object is built in postman:
{
"subject": "Test Message",
"message": "this is a test",
"sendTo": "sam#test.com"
}
I make sure that the type is marked as JSON on postman and tried formatting it in different ways, but it doesn't seem to work. The API recieves the email object but is always null.
Here's a screenshot of my postman in case I'm missing something.
Any help is appreciated.
Edit: Already tried adding "[FromBody]" and adding "email: {}" to the json but it doesn't work.
You can do 2 things:
public bool SendEmail([FromBody]EmailObj email)
Or change the body of the json object to:
{
"email": {
"subject": "Test Message",
"message": "this is a test",
"sendTo": "sam#test.com"
}
}
I found what was the mistake, I was declaring my email object as 'Serializable' and that was preventing the json object to get any value.
You can compare your controller with below code and you can click this link and see the output.
[RoutePrefix("api/test")]
public class TestController : ApiController
{
[Route("sendemail")]
[HttpPost]
public bool SendEmail(EmailObj email)
{
if(email !=null)
{
return true;
}
return false;
}
}
public class EmailObj
{
public string sendTo { get; set; }
public string subject { get; set; }
public string message { get; set; }
}
This is my postman image that how I have called the post api.
This is my WebApi.config file image.

Web API Post with multi parameter never work

How can we support ajax post?
This the server code:
[RoutePrefix("api/Dashboard")]
public class PatientDashboardController : ApiController
{
[Route("UpdatePatientById")]
[HttpPost]
public IHttpActionResult UpdatePatientById(int? pk, string name, object value )
{
return Ok(name);
}
}
This is what I post to the server
Request URL:http://localhost/mydomain/api/Dashboard/UpdatePatientById
Request Method:POST
name:sex
value:1
pk:1093
I'm using x-editable plugin on the front end, it does the ajax post automatically. I don't think there is anything wrong with the post url.
This the error it gives me:
"No HTTP resource was found that matches the request URI 'http://example.com/mydomain/api/Dashboard/UpdatePatientById'."
MessageDetail: "No action was found on the controller 'Dashboard' that matches the request."
Web API can only receive one parameter from the body so you'll have to specify it as a type that aggregates those fields.
class PatientParameters
{
public int? Pk { get; set; }
public string Name { get; set; }
public object Value { get; set; }
}
and pass that:
public IHttpActionResult UpdatePatientById([FromBody] PatientParameters parameters) { }

Categories