Search code examples
c#asp.net-mvcfiltercustom-action

Unwanted Model Binding in Custom Filter


I've got a wierd/annoying little bug which I don't even know how to properly explain so forgive me if this becomes a bit wordy. Also, objects have been renamed for their protection ;)

The MVC site I'm working on (I didn't start it I'm just working on it) has a custom filter attribute that injects a parameter into any action method that is decorated with said filter. The parameter holds the details of the logged in user which are used to determine role based privileges. See example below:

[UserFilter]
public ActionResult DoSomeStuffDependingOnPrivileges(string userId, UserObj user)

The UserObj is a model. It looks a little like this:

public class User  
{  
    [DisplayName("User ID")]  
    public int UserID { get; set; }

    ...
    ...
    ...

    public IEnumerable<RoleModels.Role> Roles { get; set; }
}

Here's the custom action filter:

public override void OnActionExecuting(ActionExecutingContext filterContext)  
{  
    if (filterContext.ActionParameters.ContainsKey(key))  
    {  
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)  
        {  
            var user = (User)filterContext.HttpContext.Session["User"];
            filterContext.ActionParameters[key] = user;
        }  
    }  

    base.OnActionExecuting(filterContext);
}

So the way it works is that the filter populates the UserObj parameter from the session stored value. It isn't passed by the code calling the action method. The idea I guess was to clean up or centralise the code or some such noble intention.

The weird thing is this: Look at the action method. I'm passing in a string parameter named userId. This userId is the ID of a different user than the one in the UserObj parameter (think of it as a manager employee relationship). When the action filter executes, it populates the user parameter as desired but for some reason it populates said user paremeter's UserID property (int) with the userId parameter (string) passed into the action method thus wich causes the ModelState to become invalid even though I did not wish to validate the UserObj model.

Why Larry why!

The work around is easy enough. renaming the userId parameter solves the problem.

My question (finally) is this: How, without resorting to changing the action method parameter name, do I stop this from happening?


Solution

  • Have you tried using BindAttribute?