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!
Similar Posts
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.