framework - ¿Es posible implementar X-HTTP-Method-Override en ASP.NET MVC?
required model asp net mvc (8)
Estoy implementando un prototipo de API RESTful usando ASP.NET MVC y aparte de los errores ocasionales aquí y allá, he logrado todos los requisitos que establecí al principio, además de que los llamadores pueden usar el X-HTTP-Method-Override
anula el encabezado personalizado para anular el método HTTP.
Lo que me gustaría es que la siguiente solicitud ...
GET /someresource/123 HTTP/1.1
X-HTTP-Method-Override: DELETE
... se enviaría a mi método de controlador que implemente la funcionalidad DELETE
lugar de la funcionalidad GET
para esa acción (suponiendo que hay múltiples métodos implementando la acción, y que están marcados con diferentes atributos [AcceptVerbs]
). Entonces, dados los dos métodos siguientes, me gustaría que la solicitud anterior sea enviada a la segunda:
[ActionName("someresource")]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetSomeResource(int id) { /* ... */ }
[ActionName("someresource")]
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult DeleteSomeResource(int id) { /* ... */ }
¿Alguien sabe si esto es posible? ¿Y cuánto trabajo sería hacer eso ...?
El X-HTTP-Method-Override es un encabezado personalizado y lo más probable es que no sea compatible con su contenedor web.
¿Estás llamando esto desde una página web? Si es así, probablemente deberías usar XmlHttpRequest con DELETE (o el verbo que quieras). Mejor aún, use un marco JS para hacer el trabajo pesado por usted.
Puede crear un ActionFilter que implementa OnActionExecuting, que se dispara antes de invocar la acción del controlador. A continuación, puede interrogar a los encabezados de solicitud y redirigir en función del valor del encabezado X-HTTP-Method-Override, cuando esté presente.
No podrá usar el atributo [AcceptVerbs] tal como está, ya que está vinculado al verbo HTTP actual de la solicitud. Afortunadamente, el atributo [AcceptVerbs] es muy simple; Puede ver la fuente en http://www.codeplex.com/aspnet/SourceControl/changeset/view/21528#266431 .
En resumen, la subclase AcceptsVerbsAttribute y anula el método IsValidForRequest (). La implementación sería algo como lo siguiente:
string incomingVerb = controllerContext.HttpContext.Request.Headers["X-HTTP-Method-Override"] ?? controllerContext.HttpContext.Request.Method;
return Verbs.Contains(incomingVerb, StringComparer.OrdinalIgnoreCase);
¿Has visto Simply Restful Routing ? Ya lo hace.
Editado en febrero de 2010 para agregar: las anulaciones de métodos están integradas en MVC 2.
La respuesta de Levi es genial. Además, agregué un cheque en el AcceptsVerbsAttribute personalizado que también examina la colección FORM, por lo que simplemente puede poner una entrada oculta para desencadenar el DELETE (similar a Html.HttpMethodOverride(HttpVerbs.Delete)
2 Html.HttpMethodOverride(HttpVerbs.Delete)
).
<input name="X-HTTP-Method-Override" type="hidden" value="DELETE" />
Cambie la asignación de Verbo entrante a:
string incomingVerb = controllerContext.HttpContext.Request.Headers["X-HTTP-Method-Override"] ?? controllerContext.HttpContext.Request.Form["X-HTTP-Method-Override"] ??controllerContext.HttpContext.Request.HttpMethod;
¡Ten cuidado con este enfoque! Ver una publicación relacionada por Stephen Walther.
Espero que esto ayude a alguien.
Insertar a la forma:
<%= Html.HttpMethodOverride(HttpVerbs.Delete) %>
Esta conversación es un poco antigua, pero quería compartir lo que he encontrado usando mvc 2:
Los navegadores admiten dos verbos HTTP: GET y POST, pero ASP.NET MVC 2 le permite simular Put, Get y Delete utilizando el método auxiliar Html.HttpMethodOverride. Internamente, esto funciona al enviar el verbo en un campo de formulario X-HTTP-Method-Override. El comportamiento de HttpMethodOverride es utilizado por el atributo [AcceptVerbs] así como los nuevos atributos de verbos más cortos:
Por ejemplo, la declaración de acción:
[ActionName("someresource")]
[HttpDelete]
public ActionResult DeleteSomeResource()
debe asumir la responsabilidad de su solicitud de obtención que tiene el X-HTTP-Method-Override configurado para Eliminar.
Me sorprende que esto aún no se haya mencionado, pero ASP.NET MVC admite nativamente X-HTTP-Method-Override y lo ha estado haciendo desde al menos la versión 2. No es necesario escribir código personalizado para manejar esto.
Funciona de la siguiente manera:
Dentro de AcceptVerbsAttribute (también representado por [HttpPut], [HttpPost], etc.), hay un método IsValidForRequest. Dentro de ese método, comprueba con Request.GetHttpMethodOverride (), que devuelve el método HTTP sobrescrito adecuado con las siguientes condiciones:
- La anulación solo se admite en solicitudes POST. Todos los demás son ignorados.
- Si el valor X-HTTP-Method-Override es GET o POST, se ignorará. Esto tiene sentido, ya que nunca necesitaría anular con estos valores.
- Busca X-HTTP-Method-Override en los siguientes lugares en esta prioridad: 1) Encabezado HTTP 2) Cuerpo del formulario 3) Cadena de consulta
Si eres realmente curioso, así es como se ve GetHttpMethodOverride () (del código fuente de MVC 3):
public static class HttpRequestExtensions {
internal const string XHttpMethodOverrideKey = "X-HTTP-Method-Override";
public static string GetHttpMethodOverride(this HttpRequestBase request) {
if (request == null) {
throw new ArgumentNullException("request");
}
string incomingVerb = request.HttpMethod;
if (!String.Equals(incomingVerb, "POST", StringComparison.OrdinalIgnoreCase)) {
return incomingVerb;
}
string verbOverride = null;
string headerOverrideValue = request.Headers[XHttpMethodOverrideKey];
if (!String.IsNullOrEmpty(headerOverrideValue)) {
verbOverride = headerOverrideValue;
}
else {
string formOverrideValue = request.Form[XHttpMethodOverrideKey];
if (!String.IsNullOrEmpty(formOverrideValue)) {
verbOverride = formOverrideValue;
}
else {
string queryStringOverrideValue = request.QueryString[XHttpMethodOverrideKey];
if (!String.IsNullOrEmpty(queryStringOverrideValue)) {
verbOverride = queryStringOverrideValue;
}
}
}
if (verbOverride != null) {
if (!String.Equals(verbOverride, "GET", StringComparison.OrdinalIgnoreCase) &&
!String.Equals(verbOverride, "POST", StringComparison.OrdinalIgnoreCase)) {
incomingVerb = verbOverride;
}
}
return incomingVerb;
}
}