Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind Json Query string in asp.net core web api

following code in asp.net web API worked fine but doesn't work in Asp.net core.

Endpoint api/devices?query={"deviceName":"example"}

[HttpGet]
public Device ([FromUri] string deviceName)
{        
        var device = context.Computers.Where(x => x.deviceName == deviceName);
        return device;
}

[FromUri] attribute is not present asp.net core web API, and I tried to use following , but no success.

[HttpGet]
public Device  Get([FromQuery] string  deviceName)
{
    return repo.GetDeviceByName(deviceName);
}
like image 1000
Rohit Avatar asked Jun 17 '17 18:06

Rohit


People also ask

How does ASP NET Core handle JSON data?

By default, ASP.NET Core includes JSON based input formatters for handling JSON data. You can add other formatters for other content types. ASP.NET Core selects input formatters based on the Consumes attribute. If no attribute is present, it uses the Content-Type header.

How do I parse JSON data in model binding?

To parse this data, model binding uses an input formatter that is configured to handle a particular content type. By default, ASP.NET Core includes JSON based input formatters for handling JSON data. You can add other formatters for other content types. ASP.NET Core selects input formatters based on the Consumes attribute.

When should I not use JSON with a web API?

Not used with a web API unless consumed from form data, query strings, and route data. Web API endpoints that consume JSON use Input formatters to deserialize the request body into an object. For more information, see TryUpdateModelAsync.

How to build query string in ASP NET Core?

Fortunately, ASP.NET Core has a static class QueryHelpers which has a function called AddQueryString offers a neat way to build query string in ASP.NET Core. The AddQueryString method has 2 definitions.


1 Answers

Unfortunately there is no way to bind JSON in a GET query like you have there. What you are looking for is to use a custom model binder to tell ASP.net Core how you want to bind.

First, you want to build your model for your JSON object.

public class MyCustomModel
{
    public string DeviceName { get; set; }
}

Next you need to build your model binder. A simple example is given below but you would obviously want other checks around if it can be converted, Try/Catch blocks etc. Essentially a model binder tells ASP.net Core how a model should be bound. You might also run into TypeConverters which are given a type, how can I change this to another type during model binding. For now let's just use modelbinders.

public class MyViewModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var jsonString = bindingContext.ActionContext.HttpContext.Request.Query["query"];
        MyCustomModel result = JsonConvert.DeserializeObject<MyCustomModel>(jsonString);

        bindingContext.Result = ModelBindingResult.Success(result);
        return Task.CompletedTask;
    }
}

So all we are doing is taking the query string and deserializing it to our model.

Next we build a provider. A provider is what tells ASP.net core which modelbinder to use. In our case it's simple, if the model type is our custom type, then use our custom binder.

public class MyViewModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.ModelType == typeof(MyCustomModel))
            return new MyViewModelBinder();

        return null;
    }
}

And the final piece of the puzzle. In our startup.cs, we find where we add MVC services and we insert our model binder to the front of the list. This is important. If we just add our modelbinder to the list, another model binder might think it should be used instead (First in first served), so we might not ever make it to ours. So be sure to insert it at the start.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(config => config.ModelBinderProviders.Insert(0, new MyViewModelBinderProvider()));
}

Now we just create an action where we read the data, no attributes required.

[HttpGet]
public void Get(MyCustomModel model)
{

}

Further reading :

  • http://dotnetcoretutorials.com/2016/12/28/custom-model-binders-asp-net-core/
  • https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding
like image 74
MindingData Avatar answered Sep 18 '22 17:09

MindingData