Как я использую пользовательское ограничение с HttpMethodConstraint в ASP.NET маршрутизация MVC?

У меня есть контроллер, который только принимает должность на этом URL:

POST http://server/stores/123/products

THE POST должна иметь тип контента application/json, таким образом, это - то, что я имею в своей таблице маршрутизации:

routes.MapRoute(null,
                "stores/{storeId}/products",
                new { controller = "Store", action = "Save" },
                new {
                      httpMethod = new HttpMethodConstraint("POST"),
                      json = new JsonConstraint()
                    }
               );

Где JsonConstraint :

public class JsonConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return httpContext.Request.ContentType == "application/json";
    }
}

Когда я использую маршрут, я получаю Запрещенные 405:

The HTTP verb POST used to access path '/stores/123/products' is not allowed

Однако, если я удаляю json = new JsonConstraint() ограничение, это хорошо работает. Кто-либо знает то, что я делаю неправильно?

8
задан Daniel T. 28 January 2010 в 23:26
поделиться

2 ответа

Я бы поставил это в комментарий, но недостаточно места.

При написании пользовательского ограничения очень важно осмотреть параметр и убедитесь, что ваша логика работает только в нужное время.

Этот параметр говорит вам, запускается ли ваше ограничение при обработке входящего запроса или запуска, когда кто-то генерирует URL (например, когда они звонят HTML.ActionLink ).

В вашем случае я думаю, что вы хотите поставить весь свой соответствующий код в гигант «Если»:

public bool Match(HttpContextBase httpContext, Route route,
    string parameterName, RouteValueDictionary values,
    RouteDirection routeDirection) 
{
    if (routeDirection == RouteDirection.IncomingRequest) {
        // Only check the content type for incoming requests
        return httpContext.Request.ContentType == mimeType; 
    }
    else {
        // Always match when generating URLs
        return true;
    }
}
8
ответ дан 5 December 2019 в 14:03
поделиться

Я бы отладил бы jsonconstraint и посмотрите, что такое тип контента.

Возможно, что по любой причине он не может быть приложения / JSON .

Я знаю, что это тип RFC MIME, но я видел несколько других, плавающих в свое время (например, текст / X-JSON ), как упоминалось здесь в Предыдущий вопрос .

Кроме того, я никогда не видел ограничения ContentType, поэтому мне было бы интересно посмотреть, работает ли это. Вы пробовали это с другими типами MIME, на случай, если это неисправен?

и, наконец, вместо того, чтобы иметь только один jsonconstraint, я бы создал общий ContentTyPeConStrint.

Обновление:

Я сбил быстрый метод Quick WebRequest на маршруте, который использует код ContentTyPecSonaint, и который, кажется, работает правильно.

enum

public enum ConstraintContentType
{
  XML,
  JSON,
}

Класс ограничения

public class ContentTypeConstraint : IRouteConstraint
{
  private string mimeType;

  public ContentTypeConstraint(ConstraintContentType constraintType)
  {
    //FYI: All this code could be redone if you used the Description attribute, and a ToDescription() method.
    switch (constraintType)
    {
      case ConstraintContentType.JSON:
        mimeType = "application/json";
        break;
      case ConstraintContentType.XML:
        mimeType = "text/xml";
        break;
      default:
        mimeType = "text/html";
        break;
    }
  }

  public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
  {
    //As suggested by Eilon
    if (routeDirection == RouteDirection.UrlGeneration)
      return true;

    return httpContext.Request.ContentType == mimeType;
  }
}

Это будет называться, используя свой пример, как:

contentType = new ContentTypeConstraint(ConstraintContentType.JSON)

Это было ограничение многократно многое другое, чем просто JSON. Кроме того, чехол переключателя может быть проведен, если вы используете атрибуты описания на классе Enum.

4
ответ дан 5 December 2019 в 14:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: