У меня есть контроллер, который только принимает должность на этом 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()
ограничение, это хорошо работает. Кто-либо знает то, что я делаю неправильно?
Я бы поставил это в комментарий, но недостаточно места.
При написании пользовательского ограничения очень важно осмотреть параметр
и убедитесь, что ваша логика работает только в нужное время.
Этот параметр говорит вам, запускается ли ваше ограничение при обработке входящего запроса или запуска, когда кто-то генерирует 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;
}
}
Я бы отладил бы 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.