Можно ли реализовать X-HTTP-Method-Override в ASP.NET MVC? - PullRequest
5 голосов
/ 22 января 2009

Я реализую прототип RESTful API с использованием ASP.NET MVC и, кроме странной ошибки здесь и там, я выполнил все требования, изложенные в начале, за исключением того, что вызывающие абоненты могут использовать X-HTTP-Method-Override настраиваемый заголовок для переопределения метода HTTP.

Мне бы хотелось, чтобы следующий запрос ...

GET /someresource/123 HTTP/1.1
X-HTTP-Method-Override: DELETE

... будет отправлен в мой метод контроллера, который реализует функциональность DELETE вместо функциональности GET для этого действия (при условии, что существует несколько методов, реализующих действие, и что они отмечены различными [AcceptVerbs] атрибуты). Итак, учитывая следующие два метода, я бы хотел, чтобы вышеприведенный запрос был отправлен во второй:

[ActionName("someresource")]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetSomeResource(int id) { /* ... */ }

[ActionName("someresource")]
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult DeleteSomeResource(int id) { /* ... */ }

Кто-нибудь знает, возможно ли это? И сколько бы это заняло ...?

Ответы [ 8 ]

5 голосов
/ 29 января 2009

Вы не сможете использовать атрибут [AcceptVerbs] как есть, поскольку он привязан к фактическому HTTP-глаголу запроса. К счастью, атрибут [AcceptVerbs] очень прост; Вы можете увидеть источник для себя в http://www.codeplex.com/aspnet/SourceControl/changeset/view/21528#266431.

Короче говоря, создайте подкласс AcceptsVerbsAttribute и переопределите метод IsValidForRequest (). Реализация будет выглядеть примерно так:

string incomingVerb = controllerContext.HttpContext.Request.Headers["X-HTTP-Method-Override"] ?? controllerContext.HttpContext.Request.Method;
return Verbs.Contains(incomingVerb, StringComparer.OrdinalIgnoreCase);
3 голосов
/ 07 июня 2010

Вставить в форму:

<%= Html.HttpMethodOverride(HttpVerbs.Delete) %>
3 голосов
/ 18 февраля 2010

Ответ Леви великолепен. Кроме того, я добавил проверку в пользовательский атрибут AcceptsVerbsAttribute, который также проверяет коллекцию FORM, так что вы можете просто поместить скрытый ввод для запуска DELETE (аналогично Html.HttpMethodOverride(HttpVerbs.Delete) в MVC 2).

<input name="X-HTTP-Method-Override" type="hidden" value="DELETE" />

Измените назначение входящего сообщения на:

string incomingVerb = controllerContext.HttpContext.Request.Headers["X-HTTP-Method-Override"] ?? controllerContext.HttpContext.Request.Form["X-HTTP-Method-Override"] ??controllerContext.HttpContext.Request.HttpMethod;

Будьте осторожны с этим подходом! См. связанный пост от Стивена Вальтера.

Надеюсь, это кому-нибудь поможет.

2 голосов
/ 22 октября 2010

Этот разговор немного староват, но я хотел бы поделиться тем, что я нашел с помощью mvc 2:

Браузеры поддерживают два HTTP-глагола: GET и POST, но ASP.NET MVC 2 позволяет имитировать Put, Get и Delete с помощью вспомогательного метода Html.HttpMethodOverride. Внутренне это работает, посылая глагол в поле формы X-HTTP-Method-Override. Поведение HttpMethodOverride используется атрибутом [AcceptVerbs], а также новыми более короткими атрибутами глагола:

Например, объявление действия:

[ActionName("someresource")]
[HttpDelete]
public ActionResult DeleteSomeResource()

должен взять на себя ответственность за ваш запрос на получение, в котором для X-HTTP-Method-Override установлено значение Delete.

1 голос
/ 31 мая 2013

Я удивлен, что это еще не было упомянуто, но ASP.NET MVC изначально поддерживает X-HTTP-Method-Override и делает это по крайней мере с версии 2. Нет необходимости писать собственный код для обработки это.

Работает следующим образом:

Внутри AcceptVerbsAttribute (также проксируемого [HttpPut], [HttpPost] и т. Д.) Есть метод IsValidForRequest. Внутри этого метода он проверяет с помощью Request.GetHttpMethodOverride (), который возвращает правильный переопределенный метод HTTP со следующими условиями:

  • Переопределение поддерживается только в запросах POST. Все остальные игнорируются.
  • Если значение X-HTTP-Method-Override равно GET или POST, оно игнорируется. Это имеет смысл, поскольку вам никогда не придется переопределять эти значения.
  • Он ищет X-HTTP-Method-Override в следующих местах в этом приоритете: 1) HTTP-заголовок 2) Форма тела 3) Строка запроса

Если вам действительно интересно, вот как выглядит GetHttpMethodOverride () (из исходного кода 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;
    }
}
1 голос
/ 22 января 2009

Вы смотрели на Просто Restful Routing ? Это уже делает это.

Отредактировано в феврале 2010 г. для добавления: Переопределения методов встроены в MVC 2.

0 голосов
/ 22 января 2009

Вы можете создать ActionFilter, который реализует OnActionExecuting, который срабатывает до вызова действия контроллера. Затем вы могли бы запросить заголовки запроса и перенаправить на основе значения заголовка X-HTTP-Method-Override, если он есть.

0 голосов
/ 22 января 2009

X-HTTP-Method-Override - это пользовательский заголовок, который, скорее всего, не поддерживается вашим веб-контейнером.

Вы звоните с веб-страницы? Если это так, вам, вероятно, следует использовать XmlHttpRequest с DELETE (или любым другим глаголом, который вы хотите). А еще лучше, используйте JS-фреймворк, чтобы выполнить тяжелую работу за вас.

...