Post request to API is receiving NULL - c#

I have an ASP.NET Core API that is expecting a POST request in the shape of a particular object -- see code sample below.
I make sure that my front-end client sends the data in that exact shape. I also make sure by inspecting my call with Fiddler that the data is being sent to the API.
When the request hits the API method though, it's null.
My first thought was that the model binder is the cause of the issue. Meaning, somehow, the data I'm sending is not matching the object my API method is expecting.
I've been staring at the code for a few hours now and it seems OK to me. Assuming that the shape of the object sent by the front-end matches the object my API is expecting, what else could be causing this issue?
I've been using similar code all over my app and everything is working fine.
My code looks like this:
[HttpPost("test")]
public async Task<IActionResult> DoSomething([FromBody]MyObject data)
{
// Some logic here...
}
Here are a few things that I'm sure about:
I'm hitting the API method so there are no routing issues
The point above also confirms that my front-end client is sending a request
I know that my front-end client is sending data -- confirmed it through Fiddler
UPDATE:
This is definitely caused by model binder. I changed the code from MyObject to dynamic to see what would happen and sure enough I'm getting the data sent by the front-end. I haven't found the exact property that's causing the issue yet but I'm close. Here's what my API method looks like for now till I find the exact cause of the issue:
[HttpPost("test")]
public async Task<IActionResult> DoSomething([FromBody]dynamic data)
{
// Some logic here...
}
UPDATE 2:
Found the issue!!!!
I had a GUID property with a null valud in it and the model binder didn't like it.

This usually happens when your object can't be deserialized from JSON request.
The best practice would be to make sure that all the request properties can accept null values (make value types properties are nullable). And then you can validate that all your action needs is provided in the request and return 400 error if not.

Related

How to get request body data from System.Mvc.Web.ActionExecutingContext in c#

Here is my method It will take only one parameter . But I want user whaterver add in request body I need to save in logging.
[HttpPost]
[LogAPIUser]
public async Task<JsonResult> GameDetail(long game)
Here is my Postman request
In ActionExecutingContext I have got only one action parameter
How can I get all body request data?
If anyone have idea please let me know
Thanks in advance.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api states that:
At most one parameter is allowed to read from the message body.
The reason for this rule is that the request body might be stored in a non-buffered stream that can only be read once.
You can try to look at this question:
WebAPI Multiple Put/Post parameters
basically, you read the whole body, and get your elements out of it.
something in the effect of
[HttpPost]
public string MyMethod([FromBody]JObject data)
{
long game = data["game"].ToObject<Long>();
long rer = data["rer"].ToObject<Long>();
}
(did not try code, might be buggy)

Is there a way in Postman to store multiple values for one key?

I am working on side-project using ASP.Net Core web api. I am currently using Postman so I can interact with custom middleware. As you can see in the picture I have a User id and would like the request header to have more than one value for the user id key. Everytime I debug the api, the request header only counts one value instead of two values. I have looked at the Postman help page but it doesn't really cover any material regarding my issue. So to condense my question, is there a way in Postman that a key (For my scenario, User Id) can hold more than one value.
Your question doesn't really make sense. Postman will send the data you put, to the server. The data you put is "1,2". At the server end, if you pull the userId value and split it on the comma, you have your two values, no?
I find it incredibly unlikely that when you pull userId at the server, the value of the header is "1" and the other id has disappeared. If the web did that loads of headers (such as your gzip, deflate, br there) would get lost and stuff wouldn't work properly
In java with spring boot framework i have idea about it we have to send List userIds from request controller method this method you have to take as post method and send that data into body part with
#PostMapping("/listUsers")
public String getList(#RequestBody List<Integer> userIds) {
// call service method
return "page";
}
Json Request from postman
{
1,2,3,4,5............
}
In dot net core
[Produces("application/json")]
[Route("api/accounts")]
public class AccountsController : Controller
{
[HttpGet]
[Route("servicesbycategoryids")]
public IActionResult ServicesByCategoryIds([FromQuery] int[] ids)
{
return Ok();
}
}

How to read parameter from Request.Body in ASP.NET Core

Context: My application is behind a central login app, whenever the user apply access to my application, my application got a http request contain the user info. And I need to retrieve the user info from the HttpRequest Body.
This is what I tried so far:
currentContext.HttpContext.Request.Query["user-name"].toString(); // got nothing
using (var reader = new StreamReader(currentContext.HttpContext.Request.Body))
{
var body = reader.ReadToEnd();
} // I can get the raw HttpRequest Body as "user-name=some&user-email=something"
Is there any method I can use to parse the parameters and values from the Request.Body?
I tried the following, got nothing either.
HttpContext.Item['user-name'] \\return nothing
Request.Form["user-name"] \\ return nothing
and the reason I am not be able to use model binding is, in the HttpRequest body, the key name is "user-name", and in c#, I can't create a variable with a "-"
Meanwhile, in the my .net 4.6 application, Request["KeyName"].toString() works just fine.
I figured out a way to convert the raw HttpRequest Body to a Query String, then read parameters from it.
Here is the code:
var queryString = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(requestBody);
string paramterValueIWant = queryString["KeyName"];
There is one problem though, when the KeyName doesn't exist in the body, it will throw an exception. So you have to null check or do a try catch.
Still I feel like there should be a better way to read the parameter, as I mentioned, in my .net 4.6 application, all I need to do is Request["KeyName"].
Assuming that we are talking about POST/PUT/PATCH call, you can use
Request.Form["KeyName"]
in your API method and set the 'contentType' of the Ajax request as application/x-www-form-urlencoded
Notice that Request is automagically available inside your method. No need to explicit call it.
When using GET/DELETE call i prefer to use
[HttpGet("{UserId}")] // api/User/{UserId}
public IActionResult Get(int UserId){
// do stuff calling directly UserId
}
Or with PUT/PATCH
[Route("User/{EntityId}/{StatusFilter}")] // api/User/{EntityId}/{StatusFilter}
[HttpPut]
public IActionResult Put(int EntityId, int StatusFilter){
// do stuff calling directly EntityId and StatusFilter
}
where you can then still take data from the Body using Request.Form["KeyName"]

.NET WEB API Put request is nulling out values of properties I don't include in the request

I've got a .NET WEB API Put request that's nulling out values of properties I don't include in the request.
Here's a good request that works as expected. No surprises here:
PUT /api/user/id
{
"nickname": "peanut",
"email": "cole#cole.com"
}
Request in question, notice email isn't sent:
PUT /api/user/id
{
"nickname": "peanut"
}
In the second request, if I don't send an email key/value, email gets set to null. Ideally, I'd leave those email untouched if a request like the second request is sent.
I would also like a user to be able to send a request like this, to purposefully sent a property to null.
{
"nickname": "peanut",
"email": null
}
I was have the same problem with ASP.net web API. I think this is the bug in API.
If we does not set property in put method, then API assign default value to that property,
like your case emailset with null.
I solved this problem by getting existed data model and then put it with changes data and send put request to update data.

How do I set out Attribute in Api Controller

is it possible to use out attribute in a Api Controller method? I'm using C#.
for exp:
[HttpGet]
public string GetWhatever(string type, string source,out int errorCode, out string errorMessage)
if it is, an example of how to call it and get the out value would be great.
No, this is not possible. Only the return value is used and sent to the client.
You should sent a proper HTTP status code and the error message in body. Have a look at this: http://www.asp.net/web-api/overview/error-handling/exception-handling
I believe you miss-understand the usage of the Web API.
Your Web Api method will not be called like any other C# class method, unless you access the library directly and reference the api controller and its method like any other C# class.
The method will be called via the ASP.NET action selector and that will depend on your HTTP verb (GET, PUT, POST, DELETE or PATCH) and depending on the type and the number of your parameters.
Now your method can return your data or returns error depending on your situation, but eventually all your responses will convert to statuscode/content/error,...etc which is what the HTTP protocol understands and deals with.
for example your method can return Ok Status code (200), or Notfound status code 404 depending on where your request found the requested resource or not.
You can start with this article about Web API 2, hopefully you get a better understanding.
Hope that helps.

Categories