C# HttpRequest – Why StringValues.Contains() Always Returns False

asp.netasp.net-corec++http-accept-headerhttprequest

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?

Best Answer

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)