hemtros
10/16/2019 - 10:44 PM

Overloading multiple api action methods and helping aspnet core to map the query string

using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyApplication.Whatever
{
    public class QueryStringConstraintAttribute : ActionMethodSelectorAttribute
    {
        private readonly IEnumerable<string> _queryParamNames;
        private readonly IEnumerable<string> _optionalParamNames;
        public QueryStringConstraintAttribute(string queryParamNames, string optionalParamNames = null)
        {
            if (string.IsNullOrWhiteSpace(queryParamNames))
            {
                throw new InvalidOperationException($"{nameof(queryParamNames)} cannot be null or empty");
            }
            _queryParamNames = queryParamNames.Split(",");

            if (!string.IsNullOrWhiteSpace(optionalParamNames))
            {
                _optionalParamNames = optionalParamNames.Split(",");
            }

        }
        public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
        {
            int optParamCount = 0;
            foreach (var qpn in _queryParamNames)
            {
                var value = routeContext.HttpContext.Request.Query[qpn];

                if (StringValues.IsNullOrEmpty(value))
                {
                    return false;
                }
            }


            foreach (var opn in _optionalParamNames ?? Enumerable.Empty<string>())
            {
                var value = routeContext.HttpContext.Request.Query[opn];

                if (!StringValues.IsNullOrEmpty(value))
                {
                    optParamCount++;
                }
            }

            var uniqueParamCounts = routeContext.HttpContext.Request.Query.Count;
            if ((uniqueParamCounts - optParamCount) > _queryParamNames.Count())
            {
                return false;
            }
            return true;
        }
    }
}


//usage (decorate methods like)
[QueryStringConstraint("activealtid")]
[QueryStringConstraint("role,assignment", "includealtids")]