TugboatCaptain TugboatCaptain - 3 months ago 15
C# Question

Modeling binding taking forever

I've got a

UserFilter
class as a parameter on a Web API 2 action method which takes ~30 seconds to complete binding. I've already stepped into the
UserFilter
class as its being created and it takes no time at all instantiate, but once its created Web API is doing something in the background accounting for the ~30 seconds and then finally starts executing my action method.

I've setup the
UserFilter
on an MVC controller in this same project and it bind instantly with no delays. It's just Web API that is having this issue.




What can I do to figure out what Web API is doing in the background?

Is there an event I can latch onto in the binding lifecycle?

[Route("all")]
[HttpPost]
public async Task<IHttpActionResult> GetUsers([FromBody]UserFilter filter)
{
// takes ~30 seconds before a breakpoint hits this next line
filter = UserFilter.InitializeFilter(filter);

var userList = await UserRepository.GetUsers(filter).ConfigureAwait(false);
return Ok(new JsonResponse(new { Users = userList, Pager = filter.Pager }));
}

public class UserFilter : BaseFilter<UserFilter, User>
{
// DO NOT REMOVE: default constructor needed for model binding
public UserFilter() : base() { }

public UserFilter(int? pageSize)
: base(pageSize)
{
}
...
}

public abstract class BaseFilter<TFilterType, TEntity>
{
// default constructor needed for model binding
public BaseFilter()
{
Pager = new Pager(null);
Init();
}

public BaseFilter(int? pageSize)
{
Pager = new Pager(pageSize);
Init();
}
...
}

Answer

Turned out to be an issue with Web API 2 model binding code. The class QueryMutatorCondition had a constructor that took generic Predicate<> and Func<> as parameters. This is what Web API was choking on.

For unknown reasons it continued to attempt to bind to the QueryMutators property (member of the BaseFilter class) even though I told it to ignore it with the attribute. The fix was to change the access modifier to internal instead of public to prevent Web API from attempting to bind to it.

[JsonIgnore]
public List<QueryMutatorCondition<TFilterType, TEntity>> QueryMutators { get; set; }

became:

internal List<QueryMutatorCondition<TFilterType, TEntity>> QueryMutators { get; set; }