Monday, August 6, 2018

ASP.NET Web API : System.InvalidOperationException: 'The inline constraint resolver of type 'DefaultInlineConstraintResolver' was unable to resolve the following inline constraint:

In this blog, I will discuss about the inline-constrain for attributeRoute and also will discuss about default inline constrain and custom constrain.

Few days backed, I designed a API route for one Undo Web API method and I tried to apply ENUM datatype validation on action in route and encountered below DefaultInlineConstrainResolver Error 

Error: System.InvalidOperationException: 'The inline constraint resolver of type 'DefaultInlineConstraintResolver' was unable to resolve the following inline constraint: 'ActionEnum’



[HttpGet]
[Route("api/orders/undo/{orderID}/action/{actiontype: OrderCorrectionActionEnum}")]
public IHttpActionResult Undo(int orderID, OrderCorrectionActionEnum actiontype)
    {
            _route(undo(orderID, action);
    }

public enum OrderCorrectionActionEnum
        {           
            [EnumMember]
            Cleared,

            [EnumMember]
            Deleted,
        }


By default Web API supports only few inline constrains

1.       Type-specific constraints – support only primitive data type (except string)
{ "bool", typeof(BoolRouteConstraint) },
{ "datetime", typeof(DateTimeRouteConstraint) },
{ "decimal", typeof(DecimalRouteConstraint) },
{ "double", typeof(DoubleRouteConstraint) },
{ "float", typeof(FloatRouteConstraint) },
{ "guid", typeof(GuidRouteConstraint) },
{ "int", typeof(IntRouteConstraint) },
{ "long", typeof(LongRouteConstraint) },

2.       Length constraints -
{ "minlength", typeof(MinLengthRouteConstraint) },
{ "maxlength", typeof(MaxLengthRouteConstraint) },
{ "length", typeof(LengthRouteConstraint) },

3.       Min/Max value constraints
{ "min", typeof(MinRouteConstraint) },
{ "max", typeof(MaxRouteConstraint) },
{ "range", typeof(RangeRouteConstraint) },

4.       Regex-based constraints
{ "alpha", typeof(AlphaRouteConstraint) },
{ "regex", typeof(RegexRouteConstraint) }




To apply ENUM constrain, you have to create custom OrderCorrectionEnumRouteConstraint by using IHttpRouteConstraint.

public class OrderCorrectionEnumRouteConstraint : IHttpRouteConstraint
        {

            public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
            {
                // You can also try Enum.IsDefined, but docs say nothing as to
                // is it case sensitive or not.
                var response = Enum.GetNames(typeof(OrderCorrectionActionEnum)).Any(s => s.ToLowerInvariant() == values[parameterName].ToString().ToLowerInvariant());
                return response;
            }

            public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
            {
                bool response = Enum.GetNames(typeof(BlockCorrectionActionEnum)).Any(s => s.ToLowerInvariant() == values[parameterName].ToString().ToLowerInvariant());
                return response;              
            }
        }

In Web API config, You have to add this constrain

  public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
           config.Services.Replace(typeof(IExceptionHandler), new APIExceptionHandler());

            // Web API Handler
           // config.MessageHandlers.Add(new APIAuthenticationHandler());

            config.Filters.Add(new APIClientTokenValidation());

            var constraintsResolver = new DefaultInlineConstraintResolver();
            constraintsResolver.ConstraintMap.Add("OrderCorrectionActionEnum", typeof(OrderCorrectionEnumRouteConstraint));       
           
            // Web API routes
            config.MapHttpAttributeRoutes(constraintsResolver);

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }              
            );
        }




You can also create generic ENUM constraints, which will be applicable for all ENUM.

Thanks for visiting!!

No comments:

SQL Server - Identify unused indexes

 In this blog, we learn about the index usage information (SYS.DM_DB_INDEX_USAGE_STATS) and analyze the index usage data (USER_SEEKS, USER_S...