2

I have an MVC method as follows which supports the [HttpGet] attribute.

[HttpGet]        
[ActionName("Index")]
public ActionResult IndexGet(string l)
{               
    return View();
}

However, I'm noticing in our web server log files we are getting a HEAD request, but since I don't have a [HttpHead] defined we are returning a 404, which is correct. The web server log file entries are for example

2020-05-20 00:00:51 W3SVC1 EC2AMAZ 10.0.0.206 HEAD / 443 - XXX.XXX.XXX.XXX HTTP/1.1 Mozilla/5.0+(compatible;+UptimeRobot/2.0;+http://www.uptimerobot.com/) - www.domainname.com 404 0 0 306 694 155

and

2020-05-20 00:01:13 W3SVC1 EC2AMAZ 10.0.0.206 GET / 443 - XXX.XXX.XXX.XXX HTTP/1.1 Mozilla/5.0+(compatible;+UptimeRobot/2.0;+http://www.uptimerobot.com/) - www.domainname.com 200 0 0 156847 674 1065

How can I add support for [HttpHead] and what should I return in the response. I tried adding both [HttpHead] and [HttpGet]

[HttpHead]  
[HttpGet]       
[ActionName("Index")]
public ActionResult IndexGet(string l)
{               
    return View();
}

but get the following in the browser

The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.

and it breaks the [HttpGet] method. If I remove the [HttpHead] and refresh the URL the [HttpGet] loads fine.

neildt
  • 5,101
  • 10
  • 56
  • 107
  • Have you tried putting HttpGet _before_ HttpHead? Also, ensure that there is actually some content being returned. – Stuart May 20 '20 at 09:54
  • @Stuart Yes, I tried both ways HttpGet then HttpHead, and also HttpHead then HttpGet. Still the same. – neildt May 20 '20 at 10:00
  • 1
    HEAD should return just the headers, no content. Can you put that attribute to a new method that just returns an OK response? – Hans Kesting May 20 '20 at 11:19
  • @HansKesting That worked thanks. Add an answer if you wish and I'll accept it. – neildt May 20 '20 at 11:32

2 Answers2

2

A HEAD request should respond with only headers, not content. So mixing with a GET shouldn't be done.

The easiest option is to create an extra method in the controller to handle that HEAD request:

[HttpHead]
[ActionName("Index")]
public ActionResult IsAlive()
{
   return Ok();
}
Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
  • 3
    This answer is incorrect. The HTTP spec requires responses to `HEAD` requests "be identical" to `GET` requests, except omitting the response body. The code in this answer, for example, will send an empty response which will have a different `Content-Length` header. See https://www.tpeczek.com/2017/10/exploring-head-method-behavior-in.html - A better way is to just use `[Route("...")]` and let ASP.NET Core handle `HEAD` and `GET` for you - there is no need to use `[HttpHead]` _and_ `[HttpGet]` in this situation. – Dai May 28 '21 at 02:21
0

The HttpGet or HttpHead attributes represents an attribute that is used to restrict an action method so that the method handles only HTTP GET requests or only HTTP HEAD requests. A request cannot be both of these so combining them causes the controller method never to match and the result is a 404 response.

The correct way to allow both GET and HEAD requests for a single controller method is to use:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Head)]
    

See the accepted answer to Respond to HTTP HEAD requests using ASP.NET MVC

Dave Anderson
  • 11,836
  • 3
  • 58
  • 79