Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure Functions V2 Deserialize HttpRequest as object

I'm surprised I can't find the answer to this but I've got an Azure function (HTTP Trigger) I simply want to deserialize the content as an object. Previously with V1 I was able to do this,

Functions V1

[FunctionName("RequestFunction")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
    // Successful deserialization of the content
    var accountEvent = await req.Content.ReadAsAsync<AccountEventDTO>();

    // Rest of the function...
}

But now with V2 it looks more like this,

Functions V2

[FunctionName("RequestFunction")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
    // Content doesn't exist on HttpRequest anymore so this line doesn't compile
    var accountEvent = await req.Content.ReadAsAsync<AccountEventDTO>();

    // Rest of the function...
}

I can get the body to access the stream from the HttpRequest object but am unsure how I would cast that to the expected object. Any ideas?

like image 699
tokyo0709 Avatar asked Oct 09 '18 17:10

tokyo0709


Video Answer


3 Answers

The API has changed a bit. As you have seen Content does not exist anymore. However you can still get the same functionality by using the extension method that is included in the Microsoft.Azure.WebJobs.Extensions.Http namespace (which should be included already as a dependency):

string json = await req.ReadAsStringAsync();

You can view the source of this extension method here

Then you would use Json.NET to deserialize (Json.NET is already a dependency too)

var someModel = JsonConvert.DeserializeObject<SomeModel>(json);
like image 158
maccettura Avatar answered Oct 22 '22 19:10

maccettura


You can bind to a custom object instead of HttpRequest. This object is created from the body of the request and parsed as JSON. Similarly, a type can be passed to the HTTP response output binding and returned as the response body, along with a 200 status code. Example:

public static partial class SayHelloFunction
{
    [FunctionName("SayHello")]
    public static async Task<ActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)]Person person, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        return person.Name != null ?
                (ActionResult)new OkObjectResult($"Hello, {person.Name}")
            : new BadRequestObjectResult("Please pass an instance of Person.");
    }
}

The model to bind to..

public class Person
{
    public Person()
    {

    }
    public Person(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
}

The HTTP request: [POST] http://localhost:7071/api/SayHello Body: { name: "Foo" }

like image 14
user3746240 Avatar answered Oct 22 '22 20:10

user3746240


If you don't know the type of your Object, you can do:

string json = await req.ReadAsStringAsync();
dynamic data = JObject.Parse(json);
like image 3
René Avatar answered Oct 22 '22 20:10

René