Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerable.OfType<>() not working as expected with route collection

I swear this doesn't make sense.

Given I have this HttpRouteCollection from Web API, I am filtering based on some custom route types, specifically IAttributeRoute. I use httpRoutes.OfType<IAttributeRoute>() but the loop is acting like there's no elements.

To be clear, when this loop gets hit, the entire collection are of type HttpAttributeRoute which directly implement IAttributeRoute. Furthermore, I have the same loop operating on the regular RouteCollection.

This doesn't work:

foreach (IAttributeRoute route in GlobalConfiguration.Configuration.Routes.OfType<IAttributeRoute>()) {
    if (!string.IsNullOrWhiteSpace(route.RouteName) && !json.ContainsKey(route.RouteName)) {
        json.Add(route.RouteName, "/" + route.Url);
    }
}

Yet, this works fine:

foreach (var route in GlobalConfiguration.Configuration.Routes)
{
    if (route is IAttributeRoute) // uhhhh?
    {
        var r = route as IAttributeRoute;
        if (!string.IsNullOrWhiteSpace(r.RouteName) && !json.ContainsKey(r.RouteName))
        {
            json.Add(r.RouteName, "/" + r.Url);
        }
    }
}

I swear I am not lying, it only works in the latter code. Like I said, doing this on a normal route collection is fine. The normal route collection has other types, not just IAttributeRoute, but the HttpRouteCollection only has IAttributeRoute, in its current state (in the future it could have different type routes). Could that be a factor?

Am I missing something or isn't OfType doing what I'm doing internally?

like image 341
kamranicus Avatar asked Nov 04 '22 07:11

kamranicus


1 Answers

I would guess it's an issue with the way HostedHttpRouteCollection handled references to its internal collection. The GetEnumerator only returns routes of type HttpWebRoute already:

public override IEnumerator<IHttpRoute> GetEnumerator()
{
    return (
        from httpWebRoute in this._routeCollection.OfType<HttpWebRoute>()
        select httpWebRoute.HttpRoute).GetEnumerator();
}

So, while it is initialized with all of the routes from RouteTable.Routes, it doesn't return them all as IEnumerable.

This being the case, I wonder when you say "it works" in the second example, does this mean it actually iterates all the items you would expect? Looking at the implementation and running an equivalent to what you posted, I would not think that it does.

like image 61
Jeff Avatar answered Nov 13 '22 20:11

Jeff