Detecting Extra Fields in ASP.NET Web API Request

This post is related to binding in ASP.NET Web API. Binding (parameter binding, to be exact) is the mechanism through which request body is bound to the action method parameter. Say you are using a DTO class as parameter and if you want to ensure a field is present in the request, you can apply Required attribute at the property level like so.

public class MyClass
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
}

With that, if request does not contain the field, IsValid will be set to false in the model. But what about the other way around? You want to ensure that no field other than what you have defined in the DTO is present. One problem in accomplishing the check is that when Web API binds the body to parameter, it empties the body stream so that you cannot read the stream yourself, after binding. Alternative is to read the stream before but then you have to do it in a message handler and pass the body content around and check the parameter after binding. It does get a bit complex. Here is an option which I think is a better alternative – use dynamic object.

So, my DTO will be like this.

public class MyClass : DynamicObject
{
    private Dictionary<string, object> fields = 
                        new Dictionary<string, object>(
                             StringComparer.OrdinalIgnoreCase);

    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }

    public bool ContainsExtra { get; private set; }

    [JsonIgnore]
    public Dictionary<string, object> Extra
    {
        get { return fields; }
    }

    public override bool TryGetMember(GetMemberBinder binder, 
                                              out object value)
    {
        return fields.TryGetValue(binder.Name, out value);
    }

    public override bool TrySetMember(SetMemberBinder binder, 
                                                  object value)
    {
        this.ContainsExtra = true;

        fields[binder.Name] = value;
        return true;
    }
}

Now, all the properties that I have defined in the class will be bound as usual. If there is a field in the request body for which a property does not exist, it is assigned to the dictionary. Here, I use a dictionary to store those extra fields but then it is not needed, if you are only interested in detecting extra fields. You can just set a flag from TrySetMember, which gets called only for those extra fields.

If you send a request body like this {“FirstName”:”Badri”, “LastName”:”Lakshmiraghavan”, “City”:”Chennai”} and let this JSON get bound to your parameter like this public string Post(MyClass c) {}, you can check for the presence of extra fields (City, in this case) by looking at c.ContainsExtra. And, if you want to look at those extra fields, you can do so looking at c.Extra.

Of course, this will work only for JSON payload!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s