Можно ли изменить ограничения маршрута ASP.NET MVC 3 так, чтобы они возвращали 400 Bad Request с телами JSON? - PullRequest
5 голосов
/ 29 февраля 2012

Я занимаюсь разработкой некоторых ресурсов REST с использованием платформы ASP.NET MVC 3. До сих пор это было здорово, мне нравится гибкость MVC 3, и с ее помощью легко создавать REST-сервисы. Одной из областей, где у меня были трудные времена, являются ограничения маршрута в Global.asax. Во-первых, кажется, что они никогда не работают должным образом (в том числе один ВСЕГДА возвращает 404, даже если входные данные наиболее точно соответствуют требованиям ограничения ... но это другой вопрос).

Во-вторых, и, что более важно, результатом, возвращаемым в случае сбоя ограничения, всегда является HTML-страница. Если предположить, что ограничения срабатывают, то, что результат будет HTML, действительно мешает, когда все потребители этих служб REST будут принимать типы данных, такие как application / json, text / xml, возможно bson и т. Д. чтобы иметь возможность напрямую устранять ошибки наших клиентов, а не просто взорвать и записать html для разрешения боковой полосы.

Можно ли изменить то, что возвращается в ответ на ограничение маршрута? Можно ли сделать то, что возвращено, динамическим, чтобы, если клиент, отправляющий запрос, принимал только application / bson, мы могли генерировать приемлемый ответ, а не просто генерировать стандартный ответ одного типа mime?

Ответы [ 2 ]

3 голосов
/ 08 марта 2012

При возврате ошибки кода вместо обращения к контроллеру необходимо реализовать собственный RouteHandler. Эта ссылка возобновляет все, на что вы можете положить палец ... и что вы можете изменить таким образом.Об "адаптации" возвращаемого типа ... вы можете сделать это в контроллере.Достаточно поставить сом, если и в некоторых случаях вы возвращаете Json (...), а в других случаях вы возвращаете View или PartialView.

Однако было бы неплохо сделать это в фильтре контроллера ...!

Я реализовал фильтр управления, который позволяет контроллеру согласовывать тип возврата с клиентом.Я очень прост ... клиент просто объявляет тип, который я хотел бы получить, либо в параметре маршрута (фрагмент URL-адреса, либо в строке запроса), либо путем публикации поля, содержащего эту информацию.Использование очень простое ... ваш rcontroller может вернуть View, возвращающий тип возврата по умолчанию, если информация от клиента не поступает.Затем фильтр автоматически «меняет» тип результата, прежде чем вызывается View, преобразуя его в то, что требуется клиенту.Возможности, обрабатываемые фильтром, представляют собой представление, имя которого выбирается клиентом или Json

. Код приведен здесь (он содержит некоторые элементы управления «подсказкой», предоставленной клиентом для предотвращения атак злоумышленников):

public class AcceptViewHintAttribute : ActionFilterAttribute
{
    private JsonRequestBehavior jsBehavior;
    public AcceptViewHintAttribute(JsonRequestBehavior jsBehavior = JsonRequestBehavior.DenyGet)
    {
        this.jsBehavior = jsBehavior;
    }
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        string hint = filterContext.RequestContext.HttpContext.Request.Params["ViewHint"];
        if (hint == null) hint = filterContext.RequestContext.RouteData.Values["ViewHint"] as string;
        if (!string.IsNullOrWhiteSpace(hint) && hint.Length<=100 && new Regex(@"^\w+$").IsMatch(hint) )
        {


                ViewResultBase res = filterContext.Result as ViewResultBase;
                if (res != null)
                {
                    if (hint == "json")
                    {
                        JsonResult jr = new JsonResult();
                        jr.Data = res.ViewData.Model;
                        jr.JsonRequestBehavior = jsBehavior;
                        filterContext.Result = jr;
                    }
                    else
                    {
                        res.ViewName = hint;
                    }
                }

        }
        base.OnActionExecuted(filterContext);
    }
}
3 голосов
/ 06 марта 2012

Errlusion может вам помочь.

Возможно, вы сможете написать некоторую пользовательскую логику для проверки заголовка HTTP Accept и / или использовать [SomeContext].Request.IsAjaxRequest(), чтобы увидеть,JSON или BSON было бы целесообразно вернуть - или просто вернуть JSON или BSON для всех типов запросов, если вы предпочитаете.

...