ASP.NET MVC — «прячем» Action

    При активном использовании функции jQuery $.ajax в ASP.NET MVC приложении может возникнуть проблема — юзер может захотеть стукнуться к Action напрямую, вводя адрес в строку браузера. С одной стороны, ничего страшного в этом нет, но желание «спрятать» Action может возникнуть. Предлагаю вот такой легкий способ решения такой проблемы, разумеется, без претензии на оригинальность и мегамонстрячество :)

    К примеру, AJAX-запрос вот такого вида

    function saveItem(imgurl) {
        $.ajax(
          {
            url: '<%=Url.Action("SaveItem") %>',
            dataType: "json",
            data: {
              categoryid: $("#categoryid").val(),
              itemid: null,
              name: $("#name").val()
            },
            success: function(data) { $("div[id^=edititem]").html('').hide(); getItems($("#categoryid").val()); },
            error: function(e) { alert(e.responseText); }
          }
        )
      }

    * This source code was highlighted with Source Code Highlighter.


    вызывает метод SaveItem, доступ к которому можно легко получить из строки браузера. Чтобы этого не случилось, я использую вот такой маленький ActionFilterAttribute:

    public class AjaxFilterAttribute : ActionFilterAttribute
      {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
          if (!filterContext.HttpContext.Request.IsAjaxRequest())
          {
            filterContext.Result = new RedirectToRouteResult("Error",
                                             new RouteValueDictionary(
                                              new
                                                {
                                                  controller = "Home",
                                                  action = "Error"
                                                }));
          }

        }
      }

    * This source code was highlighted with Source Code Highlighter.


    Теперь достаточно любому методу, возвращающему ActionResult, проставить атрибут [AjaxFilter], и юзер, захотевший вызвать его напрямую, будет огорчен. Разумеется, нужно создать View Error.aspx и соответствующий метод в контроллере Home (или там, куда будете переадресовывать)
    Поделиться публикацией

    Комментарии 15

      0
      А чё, мне нравится, в духе MSFT и соответствует дизайну фрэймворка.
        0
        хорошо
        подумалось, может имеет смысл вызывать исключение вместо редиректа на страницу с описанием ошибки?
        типа
        new HttpException(404, «Page not found»)
          0
          Ну, это уже по желанию. В принципе, да, было бы логичным 404 выдавать в таком случае.
          0
          Ценный пост. Спасибо.

          Кстати, вы не подскажете как бороться с тем, что при $.post объекта созданного в javascript не вызывается action на сервере? Я уже замучился с этим. Видимо с сериализацией объекта на jquery или методом передачи что то не то.
            0
            Случайно, не 404 ошибка?
              0
              Нет, просто не доходит до серверного метода. Вот тут тоже парень мучался.

              stackoverflow.com/questions/848463/controller-parameter-null-when-using-jquery-post-and-asp-net-mvc
                0
                Вероятно, я понял, в чем проблема, у меня подобное было. К сожалению, я не смог (не захотел?) детально разобраться, где тут грабли, но пока обхожу эту штуку вот так:

                К примеру, у меня есть экшен, принимающий параметр name, и в правилах роутинга прописано что-то типа "{controller}/{action}/{name}". Сам же экшен выглядит как

                public ActionResult DoSomething(string name) {...}

                Когда ты посылаешь запрос типа
                $.ajax(
                 {
                  url: "/Home/DoSomething",
                  data : { name : "myname" },
                  ...
                )


                * This source code was highlighted with Source Code Highlighter.


                то как раз происходит подобная вещь. Но стоит только изменить запрос на
                $.ajax(
                {
                 url: "/Home/DoSomething/" + name,
                 ...
                )

                как все чудесным образом срабатывает :) И проследи, чтобы в случае с JSON в $.ajax был dataType: «json», а экшен возвращал JsonResult.
                Надеюсь, это как раз твой случай, и я помог.
                ЗЫ. Кстати, у этого парня другая проблема была, он о решении сам же и написал.
                  0
                  А если объект сложнее чем { name: «myname» }?

                  Если там три string и два double и ещё один объект внутри?
                    0
                    Попробовал смоделировать такую ситуацию, не возникло никаких проблем, да и раньше не сталкивался с подобным. Пока в голову ничего не приходит, увы :(
                    Пришли код в приват, посмотрю, может, и подскажу.
            +1
            А я при отправке данных формы через jQuery использую $.post и обхожусь стандартным декоратором Action — [AcceptVerbs(HttpVerbs.Post)]. И никаких лишних телодвижений.
              0
              Ну, я и написал, что это не такая уж жуткая проблема. Просто я чисто из собственных эгоистических побуждений предпочитаю, чтобы адресная строка браузера на моем сайте использовалась только для доступа к страницам, которые я предпочту показать. Использование же $.post просто ограничивает число способов, которыми можно при этом воспользоваться :)
                0
                А я не прописывал AcceptVerbs, но у меня тоже все работает.
                  0
                  Если их не прописывать, то ваш Action будет обрабатывать и GET и POST запросы. Как бы для однозначного разграничения методов по принимаемым запросам. Вроде как во второй версии MVC был отдельный декоратор для ajax. Но это для меня уже тайна, я свернул работу в ASP.NET =\
                +1
                У тебя нет проблем с безопасностью когда используется много ajax get?
                haacked.com/archive/2009/06/25/json-hijacking.aspx

                  0
                  Весьма интересная ссылка. К счастью, я редко использую get и еще реже JsonResult, и, к счастью, в тех местах, где я их использую, важные данные не возвращаются. Теперь буду еще осторожнее, спасибо.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое