(C# ASP.NET Core) BindAsync for Customized Binding of WebApi Parameters

BindAsync is a second method for custom binding of parameters. The first one - TryParse - is good for cases where the items are available in a single string - most ideally as in a query string, or a header value, or a route segment. However, if need a greater control over the binding process, then a more robust parameter such as the HttpContext is more suitable - and the BindAsync method does exactly that. It provides a signature that contains HttpContext as a parameter.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

The WebApi that we shall custom bind

Let's have a look at the web api that we shall use for this tutorial.

Open the solution explorer of the project attached to this video. Locate the program.cs file and double click to open it! Scroll to the part that you are seeing here.


// program.cs file 

using MyRazorApp.Models;

var builder = WebApplication.CreateBuilder();

builder.Services.AddRazorPages();

var app = builder.Build();

// GET API /location?p=1,2,3 

app.MapGet("/location", (MyPoint? p) =>
{
    // check integrity of conversion 
    if ((p?.x is float.NaN) || (p?.y is float.NaN) || (p?.z is float.NaN))
    {
        // 404 
        return Results.NotFound("bad data");
    }

    return Results.Ok($"({p?.x}, {p?.y}, {p?.z})");

});

app.MapRazorPages();

app.Run();


This is a GET api, and it is the same api that we discussed in the previous tutorial on binding with the TryParse method.

And, in this tutorial too, we shall be binding a query string of three comma seprated co-ordinates into a parameter of a custom class MyPoint.

If the binding fails - which can be ascertained from a NaN on any one of x, y or z - the api returns a 404 error. Otherwise it returns 200 OK.

Video Explanation (see it happen!)

Please watch the following youtube video:

Using BindAsync for Binding

Next we have to add a BindAsync function to the class MyPoint. It has to be a static function that returns a ValueTask. If you are new to a ValueTask, then you can think of it as an optimized Task. For more you can refer one of the previous tutorials where I have explained it in greater clarity.


public static ValueTask<?> BindAsync(HttpContext);

Open the solution explorer and locate the MyPoint.cs file, and double to open it.

This class has three data members - x, y and z.

// class 
public class MyPoint 
{

  // x co-ord 
  public float x { get; private set; }

  // y co-ord 
  public float y { get; private set; }

  // z co-ord 
  public float z { get; private set; }

  // this is to be added 
  public static ValueTask<MyPoint?> BindAsync(HttpContext context)
  {

    MyPoint p = new MyPoint();

    String qs = context.Request.Query["p"];

    // extract comma separated: 1,2,3 
    string[]? xyz = qs?.Split(',');

    int args = (null == xyz ? 0 : xyz.Length);

    p.x = ((args > 0) && float.TryParse(xyz?[0], out float _x)) ? _x : float.NaN;

    p.y = ((args > 1) && float.TryParse(xyz?[1], out float _y)) ? _y : float.NaN;

    p.z = ((args > 2) && float.TryParse(xyz?[2], out float _z)) ? _z : float.NaN;

    return ValueTask.FromResult<MyPoint?>(p);

  }

}

Then we have added the BindAsync function. This function uses the HttpContext parameter to extract the string contained in a querystring parameter p. The remaining code does the parsing and returns a ValueTask of the parsed instance.

Put a break-point on the return statement so that we can verify that this function is indeed called when the web-api makes a custom binding.

Run the Project and Verify

Run the project and allow the home page to open. This ensures that the server is up and running.

Next make a call to the web api by passing a query string parameter p as you are seeing here - /location?p=1,2,3

we verify that the break point in the BindAsync function is hit, and also that the server responds back by echoing the parsed object. Thanks!


This Blog Post/Article "(C# ASP.NET Core) BindAsync for Customized Binding of WebApi Parameters" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.