user917670
user917670

Reputation: 871

QueryString not being parsed correctly

I have a request to one of my actions in a controller that expects an enum as a key in the Querystring. I can see that the same is set in the QueryString but an exception is thrown by the server saying the same is not set and the error:

The parameters dictionary contains a null entry for parameter 'enumVar' of non-nullable type.

is thrown.

Here are the exception details:

Exception type: System.ArgumentException

Exception message: The parameters dictionary contains a null entry for parameter 'enumVar' of non-nullable type 'NameSpace.Enums.MyEnum' for method 'System.Web.Mvc.ActionResult GetContent(Int64, NameSpace.Enums.MyEnum, System.String, Int32, Int32, Int32, Int32, Int64)' in 'NameSpace.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.

Parameter name: parameters

Request URL: http://myawesomeurl.local/app/My/GetContent?abc=a_123&xyz=434&enumVar=EnumValue&teamId=a_123&a=0&b=1&c=3&qwerty=123&token=234234231

Request path: app/My/GetContent

Let me know if you need more information. I am not sure how I should address the issue.

Update: My Enum defination:

public enum DisplayMode
{
    EnumValue,
    EnumValue1,
    EnumValue2
}

Also I should mention that the request fails only sometimes and not always and this is not consistent. This is an error that was logged in our exception db.

Upvotes: 2

Views: 1882

Answers (2)

ErikE
ErikE

Reputation: 50191

Pro Tip: don't name action method parameters action.

MVC puts the actual controller action method name in there, no matter what you've got in your querystring or your form (assuming you are using an {action} segment in your route). Route variables take precedence over everything, so if you happen to be trying to bind an Enum with a parameter name that's reserved, it simply ain't gonna wurk.

Upvotes: 4

user596075
user596075

Reputation:

It looks like the Default Model Binder is not dailed into enumerations. Your best bet would be to subclass the DefaultModelBinder class and handle the scenario where a property is an enum.

public class U413ModelBinder : DefaultModelBinder 
{ 
    /// <summary> 
    /// Fix for the default model binder's failure to decode enum types when binding to JSON. 
    /// </summary> 
    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, 
        PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) 
    { 
        var propertyType = propertyDescriptor.PropertyType; 
        if (propertyType.IsEnum) 
        { 
            var providerValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
            if (null != providerValue) 
            { 
                var value = providerValue.RawValue; 
                if (null != value) 
                { 
                    var valueType = value.GetType(); 
                    if (!valueType.IsEnum) 
                    { 
                        return Enum.ToObject(propertyType, value); 
                    } 
                } 
            } 
        } 
        return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder); 
    } 
} 

Code and logic courtesy of this question.

Upvotes: 1

Related Questions