Brandon - Free Palestine
Brandon - Free Palestine

Reputation: 16656

How to bind remaining query parameters to a dictionary in ASP.NET Core

I'm using model binding for an ASP.NET Core application, and it has several known attributes configured, and then a dictionary where I want any additional URL attributes to be added. I want my query string to look like this:

/foobar?Id=5&Status=pending&SpecialKey=test

And for it to populate my model where the property Id = 5, Status = Pending, and to have a Dictionary called ExtraParams with one item, the key of "SpecialKey" and the value of "test".

Here's my model now:

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;

namespace MyProject.Models
{
    public class MyCustomModel
    {
        public string? Id { get; set; }
        public string? Status { get; set; }
        public string? SerialNumber { get; set; }
        public string? Nickname { get; set; }
        public string? DisplayName { get; set; }

        [JsonExtensionData]
        public Dictionary<string, object> ExtraParams { get; set; } = new Dictionary<string, JToken>();
    }
}

As it stands now, only Id/Status get populated. The only way I can get anything in ExtraParams is by using the query string notation of ExtraParams[key]=test which I do not want.

Upvotes: 4

Views: 3205

Answers (2)

skamble89
skamble89

Reputation: 131

I had a similar usecase. Following are the steps that I used

  • Add an optional parameter to Controller action method
public async Task<IActionResult> GetAllItemsAsync(string searchString, int? pageNo = 1, int? pageSize = 10, Dictionary<string, object> filters = null)
{
   <My-Controller-Logic>
}
  • Created an ActionFilterAttribute override
    public class QueryStringActionFilter : ActionFilterAttribute
    {
        private const string _additionalParamsFieldName = "filters";

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var filters = new Dictionary<string, object>();
            foreach (var kvp in context.HttpContext.Request.Query)
            {
                if (!context.ActionArguments.ContainsKey(kvp.Key))
                {
                    filters.Add(kvp.Key, kvp.Value);
                }
            }
            context.ActionArguments[_additionalParamsFieldName] = filters;
            base.OnActionExecuting(context);
        }
    }
  • Added the Action filter attribute to my controller action method
[QueryStringActionFilter]
public async Task<IActionResult> GetAllItemsAsync(string searchString, int? pageNo = 1, int? pageSize = 10, Dictionary<string, object> filters = null)
{
   <My-Controller-Logic>
}

This way all my query parameters other than searchString, pageNo and pageSize get populated inside filters.

Upvotes: 5

Alireza Mahmoudi
Alireza Mahmoudi

Reputation: 994

One way is populating all the parameters into a dictionary on your back-end using this sample code:

Dictionary<string, string> parameters = HttpContext.Current.Request.QueryString.Keys.Cast<string>()
            .ToDictionary(k => k, v => HttpContext.Current.Request.QueryString[v]);

or even this could be helpful.

Upvotes: 1

Related Questions