Search code examples
c#asp.netasp.net-corehttprequesthttp-accept-header

StringValues.Contains() always returns false


I'm trying to check if an Accept header includes a MIME type like this:

public static bool AcceptsView(this HttpRequest request) => request.Headers.Accept.Contains("text/html");

However even when the Accept header is Accept: text/html, text/plain, application/json it returns false. What am I doing wrong?


Solution

  • The Microsoft.AspNetCore.Http.HttpRequest defines a property called Headers which is an IHeaderDictionary. This interface defines an Accept property which is a StringValues. This type basically a string collection which implements a lots of interfaces, like IEnumerable<string>.

    Whenever you call Contains on the Accept that checks whether the provided string is present in the collection. In your case this property contains a single element. Not one element per acceptable mime type.

    So, you have a collection with a single element text/html, text/plain, application/json and you are checking whether it has an element with text/html. That's the reason why it always returns false.

    Option 1

    So, you should check whether is there any item inside the StringValues collection which contains the provided string:

    request.Headers.Accept.Any(x => x.Contains("text/html"))
    

    Option 2

    Another way to perform this check is to use the GetTypedHeaders. This will return a RequestHeaders instance. Its Accept property is not a StringValues rather a IList<MediaTypeHeaderValue>. So, here you have one MediaTypeHeaderValue per acceptable mime type.

    The MediaTypeHeaderValue has a property called MediaType. Its type is a StringSegment which does have a Value property.

    request.GetTypedHeaders().Accept.Any(x => x.MediaType.Value == "text/html")
    

    You can also avoid hard coding text/html. The System.Net.Mime namespaces defines several classes like MediaTypeNames or MediaTypeNames.Text. The latter one has a constant called Html which contains the text/html

    request.GetTypedHeaders().Accept.Any(x => x.MediaType == MediaTypeNames.Text.Html)