Сделайте все методы действия контроллера ChildActionOnly

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

Пытаюсь поставить ChildActionOnly Атрибут в классе контроллера не работает (по крайней мере, в моем контексте кода), потому что во время внедрения зависимостей для контроллеров, которое происходит на ранней стадии в конвейере запросов, нет объекта HttpContext или Request, и появляется ошибка "Запрос недоступно в этом контексте "брошено.

Могу ли я создать RouteConstraint что заставляет сам маршрут применять ChildActionOnly? Это кажется сомнительным из-за той же проблемы конвейера запросов - я не знаю, будет ли HttpContext доступен во время выполнения RouteConstraints. Если у вас есть идеи, как это реализовать, пожалуйста, поделитесь.

Может быть, создать модульный тест, который использует отражение, чтобы обнаружить все методы действия конкретного контроллера и убедиться, что они имеют ChildActionOnly набор атрибутов...

Как мне это сделать? Не могли бы вы дать какой-нибудь стартовый код (не нужно полировать или даже работать, только начальная точка поможет).

2 ответа

Решение

Как насчет фильтров? Вы можете создать свой собственный фильтр, а затем просто добавить фильтр в FilterConfig. Фильтры в MVC позволяют добавлять бизнес-логику (код) до / после выполнения действия, в примере для каждого запроса к действию сначала выполняется, а затем действие, и вы можете получить доступ к:

HttpContext.Current.Session filterContext.HttpContext.Request

и вы можете перенаправить

filterContext.Result = new RedirectResult.

Существуют различные типы фильтров: 1. Фильтры аутентификации (Новое в ASP.NET MVC5) 2. Фильтры авторизации 3. Фильтры действий 4. Фильтры результатов 5. Фильтры исключений

в приведенном ниже примере я создаю пользовательский фильтр для авторизации

 public class CustomFilter : FilterAttribute, IAuthorizationFilter
 {
    public void OnAuthorization(AuthorizationContext filterContext)
    {

       if (!UserRepository.IsValidUserBy(HttpContext.Current.Session["userName"].ToString()))
            {
                filterContext.Result = new RedirectResult("~/User/AccessDenied", true);
            }
    }
   }

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new MyExpirePageActionFilterAttribute());
       filters.Add(new CustomFilter ());

    }

Я нашел этот вопрос и ответ, пока гуглял, как добиться именно этого сам.
Хотя этот вопрос касается конкретно MVC4, и мой ответ не имеет к этому непосредственного отношения, все же представляется уместным указать, что MVC 5 теперь поддерживает использование [ChildActionOnly] атрибут на весь контроллер, что делает возможным следующее:

namespace MyWebApp.Controllers
{
   [ChildActionOnly]
   public class MyController
   {
      //Can only be called from another action
      public ActionResult MyAction()
      {
         return View();
      }
   }
}

который при переходе непосредственно к http://myapp.com/MyController/MyAction приводит к возвращению следующего:

Server Error in '/' Application.

The action 'MyAction' is accessible only by a child request. 
  Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace

Для получения дополнительной информации об ошибке и ее возникновении в коде.

 Exception Details: System.InvalidOperationException: The action 'MyAction' is accessible only by a child request.
Другие вопросы по тегам