JSON is not deserializing [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Something is just wrong here and I can't figure it out.
I am POSTing to an Azure Function in Visual Studio 2019/c# in debug. The POST looks like this:
In debug, the requestBody is grabbed from the stream and put into a string. I am deserializing the JSON into an object (I've tried dynamic as well) but the object is not populated. In fact, the object "data" doesn't even seem to exist. See the image where I am at a breakpoint and the value "data" doesn't even exist:
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = String.Empty;
using (StreamReader streamReader = new StreamReader(req.Body))
{
requestBody = await streamReader.ReadToEndAsync();
}
var data = JsonConvert.DeserializeObject<AppInfo>(requestBody);
string responseMessage = string.IsNullOrEmpty(data.UserGuid) ? "User not logged" : "User logged";
return new OkObjectResult(responseMessage);
}
public class AppInfo
{
public string AppName = "";
public string UserGuid = "";
}

I am using below code I can get the Json deserialize object. Please check below
I tried with both dynamic and Var datatype to store the json deserialize object
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var data = JsonConvert.DeserializeObject<AppInfo>(requestBody as string);
var val = JsonConvert.SerializeObject(data);
string responseMessage = string.IsNullOrEmpty(data.UserGuid) ? "User not logged" : "User logged";
return new OkObjectResult(responseMessage);
}
public class AppInfo
{
public string AppName = "";
public string UserGuid = "";
}

This wasn't a code issue, but a problem with Visual Studio.
This was a part of a bigger project. The other project I was going to send to release but decided to add some additional functionality. I had changed the build to "release" and then added this code. It wasn't able to run this code properly for whatever reason until I set the build type to "debug" - then the code started working properly.

Related

HTTP trigger azure function having problems when not running locally

I have a basic HTTP trigger azure function in Visual Studio (C#):
[FunctionName("HttpTriggerCSharp")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
But I'm having 2 issues with this:
(1) I only want it to receive 'Post' requests. But when I take out the "get" from the arguments the function no longer receives my requests in Azure. I get a 404 Not Found. But locally it stills receives my request and works fine.
(2) Additionally the body of the request is not received in Azure. Its empty. Once again when running locally no such problems occur.
I found several cases of people having the issue (2), but haven't found a way to solve. As to issue (1), haven't found any similar cases posted online yet.
Does anyone have any idea on why this is happening?

Why can't my ASP.NET Core 2 method return TwiML?

I have an ASP.NET Core 2 application and I'm trying to forward a call made to a Twilio number to another number. When I try to return TwiML I get an error that says:
"Non-invocable member 'TwiML' cannot be used like a method."
Here's the method:
[HttpPost]
public TwiMLResult ForwardCall(string called)
{
var response = new VoiceResponse();
response.Dial(newNumber);
return TwiML(response);
}
The error happens here:
return TwiML(response);
All the code examples I've seen tell me to return the TwiML this way but for some reason, I'm unable to.
The problem was that the controller was not inheriting from TwilioController. Once I had my controller inherit from TwilioController the error went away.
Since TwiML is just XML, I would consider returning a ContentResult instead.
The ContentResult object is an ActionResult that returns a simple string. It also supports setting the Content-Type that will be returned with the response:
[HttpPost]
public ContentResult ForwardCall(string called)
{
var response = new VoiceResponse();
response.Dial(newNumber);
return new ContentResult(TwiML(response), "text/xml");
}
If you are having this problem from an Azure Function, and you cant inherit from the TwilioController, something like this will work, after all TwiML is just XML.
[FunctionName("ProcessCall")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
var voiceResponse = new VoiceResponse();
voiceResponse.Dial(number: "<NumberGoesHere>");
return new HttpResponseMessage
{
Content = new StringContent(voiceResponse.ToString(), System.Text.Encoding.UTF8, "application/xml")
};
}
Probably more .net nuget related, but I had to uninstall/re-install twilio package before visual studio recognized the Twilio.Aspnet namespace.

Retrieving body of json Object of an http Request C#

I have the problem, that I can't retrieve the body of a POST statement of a JSON Object. Here is the function, which is called when executing the http-Request:
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "HttpTriggerCSharp/name/{name}")]HttpRequestMessage req, string name, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
string output = JsonConvert.SerializeObject(req.Content.ToString());
// Fetching the name from the path parameter in the request URL
return req.CreateResponse(HttpStatusCode.OK, output);
}
Im executing the POST with Postman and the following URL: http://localhost:7071/api/HttpTriggerCSharp/name/test
In the Header I wrote "Content-Type: application/json" and the Body looks like this:
{
"Benutzer":"Nenad",
"Passwort":"test"
}
My result is this: "\"System.Net.Http.StreamContent\""
Thank you for your help!
Thanks for the answers guys,
i found now an other solution with the help of a friend, this is the following:
public static async System.Threading.Tasks.Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "HttpTriggerCSharp/name/{name}")]HttpRequestMessage req, string name, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
dynamic dataArray = await req.Content.ReadAsAsync<object>();
string output = dataArray.ToString();
var data = Newtonsoft.Json.JsonConvert.DeserializeObject<Benutzer>(output);
// Fetching the name from the path parameter in the request URL
return req.CreateResponse(HttpStatusCode.OK, data);
}
Content is an instance of HttpContent class (as you can see in your output). So you have to use an appropriate method to get the string.

Azure Functions C# Http Trigger does not return response

If have a simple HTTP triggered function in C# which just doesn't return the result:
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
string jobId = req.Headers.GetValues("scheduler-jobid").FirstOrDefault();
string executionTime = req.Headers.GetValues("scheduler-expected-execution-time").FirstOrDefault();
return req.CreateResponse(HttpStatusCode.OK,new {
JobId = jobId,
ExecutionTime = executionTime}
);
}
I checked with POSTMAN that HTTP headers are set correctly but just get a 200 OK without a response body.
In hindsight the solution is obvious:
I had to define a HTTP Response output and without changing the code above the Azure Functions runtime automatically wires in the req.CreateResponse.

Read HttpContent in WebApi controller

How can I read the contents on the PUT request in MVC webApi controller action.
[HttpPut]
public HttpResponseMessage Put(int accountId, Contact contact)
{
var httpContent = Request.Content;
var asyncContent = httpContent.ReadAsStringAsync().Result;
...
I get empty string here :(
What I need to do is: figure out "what properties" were modified/sent in the initial request (meaning that if the Contact object has 10 properties, and I want to update only 2 of them, I send and object with only two properties, something like this:
{
"FirstName": null,
"LastName": null,
"id": 21
}
The expected end result is
List<string> modified_properties = {"FirstName", "LastName"}
By design the body content in ASP.NET Web API is treated as forward-only stream that can be read only once.
The first read in your case is being done when Web API is binding your model, after that the Request.Content will not return anything.
You can remove the contact from your action parameters, get the content and deserialize it manually into object (for example with Json.NET):
[HttpPut]
public HttpResponseMessage Put(int accountId)
{
HttpContent requestContent = Request.Content;
string jsonContent = requestContent.ReadAsStringAsync().Result;
CONTACT contact = JsonConvert.DeserializeObject<CONTACT>(jsonContent);
...
}
That should do the trick (assuming that accountId is URL parameter so it will not be treated as content read).
You can keep your CONTACT parameter with the following approach:
using (var stream = new MemoryStream())
{
var context = (HttpContextBase)Request.Properties["MS_HttpContext"];
context.Request.InputStream.Seek(0, SeekOrigin.Begin);
context.Request.InputStream.CopyTo(stream);
string requestBody = Encoding.UTF8.GetString(stream.ToArray());
}
Returned for me the json representation of my parameter object, so I could use it for exception handling and logging.
Found as accepted answer here
Even though this solution might seem obvious, I just wanted to post it here so the next guy will google it faster.
If you still want to have the model as a parameter in the method, you can create a DelegatingHandler to buffer the content.
internal sealed class BufferizingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
await request.Content.LoadIntoBufferAsync();
var result = await base.SendAsync(request, cancellationToken);
return result;
}
}
And add it to the global message handlers:
configuration.MessageHandlers.Add(new BufferizingHandler());
This solution is based on the answer by Darrel Miller.
This way all the requests will be buffered.

Categories