0

I have an ActionFilterAttribute where I expect a ViewModel with one of its paramaters as a string.

I read it in the "OnActionExecuting(HttpActionContext actionContext)" method.

As a test, I am sending this parameter as a boolean value: true (instead of a string and without quotes), but the framework is automatically transforming this true boolean into "true" as a string.

Is there a way I can validate that this input parameter is a true or a "true"?

Ashley Medway
  • 7,151
  • 7
  • 49
  • 71
user441365
  • 3,934
  • 11
  • 43
  • 62
  • Is this MVC or WebAPI as `OnActionExecuting(HttpActionContext actionContext)` is a WebAPI filter and `OnActionExecuting (ActionExecutingContext actionContext)` would be MVC? It's possible you have the wrong type of `ActionFilterAttribute`. If you can confirm if this is meant to be MVC or WebAPI then I can give an example. – Ashley Medway Nov 27 '17 at 17:00
  • it's web api. When I send a boolean to a controller that is expecting a string the framework converts the true boolean into a "true" string. I guess this is done out of the box by the framework but I'd like to control this and show a validation message if they send a bool instead of a string – user441365 Nov 28 '17 at 09:03

1 Answers1

0

So if I understand correctly I think what you actually want is a custom model binder.

public class NoBooleanModelBinder : IModelBinder
{
    public bool BindModel(
        HttpActionContext actionContext,
        ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(string))
        {
            return false; //we only want this to handle string models
        }

        //get the value that was parsed
        string modelValue = bindingContext.ValueProvider
            .GetValue(bindingContext.ModelName)
            .AttemptedValue;

        //check if that value was "true" or "false", ignoring case.
        if (modelValue.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase) ||
            modelValue.Equals(bool.FalseString, StringComparison.OrdinalIgnoreCase))
        {
            //add a model error.
            bindingContext.ModelState.AddModelError(bindingContext.ModelName,
                "Values true/false are not accepted");

            //set the value that will be parsed to the controller to null
            bindingContext.Model = null;
        }
        else
        {
            //else everything was okay so set the value.
            bindingContext.Model = modelValue;
        }

        //returning true just means that our model binder did its job
        //so no need to try another model binder.
        return true;
    }
}

Then you might do something like this in your Controller:

public object Post([ModelBinder(typeof(NoBooleanModelBinder))]string somevalue)
{
    if(this.ModelState.IsValid) { ... }
}
Ashley Medway
  • 7,151
  • 7
  • 49
  • 71
  • ah so maybe what I need to do is override the default model binder. I don't want it to automatically convert a boolean into a string. I'll have a look at the source code to see how the handle this case. thanks – user441365 Nov 28 '17 at 13:07
  • Yeah so this model binder will check if the type is mean to be a string with `bindingContext.ModelType != typeof(string)` then if the type was meant to be a string check that that type is not `true` or `false`. – Ashley Medway Nov 28 '17 at 13:40
  • I'd say that this might be overkill and just allow the value? – Ashley Medway Nov 28 '17 at 13:41
  • I'd probably end up ignoring it yes, but I'd like to see if it's possible to do it without much effort – user441365 Nov 28 '17 at 14:22