D
D
Dmitry Petrov2011-12-22 10:31:26
ASP.NET
Dmitry Petrov, 2011-12-22 10:31:26

Action filtering in MVC, two-tier approach - is there a standard solution?

Suppose we have a controller

    [Authorize(Roles="Admin")]
    public class AdminController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        public ActionResult Index2()
        {
            return View();
        }
    }


The filter disables access to the entire controller if the user does not have the Admin role. Usual approach.
Change controller:
    [Authorize(Roles="Admin")]
    public class AdminController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

       [Authorize(Roles="Admin2")]
        public ActionResult Index2()
        {
            return View();
        }
    }


A filter by the Admin2 role has been added to the Index2 method. If the user has the Admin role, then he will go to Index, if there are Admin and Admin2, then he will go to Index and Index2. And if it is necessary to start up the user in Index2, but NOT to start up in Index? That is, so that the filter first checks the accessibility of the controller to the user, and then the accessibility of the method to the user, if the method is available, but the controller is not, it is allowed into the method.
I wrote my own wrapper for ActionFilterAttribute:

    //Проверка метода на доступность пользователю. Применяется к методу так: 
    //    [Inc.Modules.Output(AccessType=Inc.Modules.OutputAttribute.eAccessType.Everybody)]
    [AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
    public class OutputAttribute : ActionFilterAttribute
    {
        public enum eAccessType
        {
            None, //Никому
            Everybody, //Всем
            Authorized //Авторизованным
        }

        private eAccessType mAccessType = eAccessType.None;
        public virtual eAccessType AccessType
        {
            get { return mAccessType; }
            set { mAccessType = value; }
        }

        public OutputAttribute()
        {

        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            OnActionExecutingFilter(filterContext, mAccessType);
        }

        //Проверяем доступность метода пользователю.
        protected bool OnActionExecutingFilter(ActionExecutingContext filterContext, eAccessType accessType)
        {
            try
            {
                switch (accessType)
                {
                    case eAccessType.None:
                        filterContext.Result = new EmptyResult();
                        return false;

                    case eAccessType.Authorized:
                        break;

                    case eAccessType.Everybody:
                        break;
                }
            }
            catch (Exception ex)
            {

            }

            base.OnActionExecuting(filterContext); 
            return false;
        }
    }

    //Проверка класса на доступность пользователю. Применяется к классу так: 
    //    [Inc.Modules.OutputClass(AccessType=Inc.Modules.OutputAttribute.eAccessType.Everybody)]
    [AttributeUsage(AttributeTargets.Class)]
    public class OutputClassAttribute : OutputAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //По-умолчанию проверяем на основе атрибута класса.
            eAccessType accessType = AccessType;

            try
            {
                //Получаем атрибут вызываемого метода. Если есть - проверяем на основе него.
                object[] attributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(OutputAttribute), false);
                if (attributes != null && attributes.Length > 0)
                {
                    OutputAttribute attrib = (OutputAttribute)attributes[0];
                    accessType = attrib.AccessType;
                }
            }
            catch (Exception ex)
            {

            }

            OnActionExecutingFilter(filterContext, accessType);

        }
    }

Answer the question

In order to leave comments, you need to log in

4 answer(s)
B
Bob Smith, 2014-11-01
@bob_smith

There is no standard solution. Your decision is quite logical.
I just decided to find the oldest unanswered question and answer it :-)

S
Samuel_Leonardo, 2013-10-07
@Samuel_Leonardo

tableviewcell is designed to create custom cell views in the visual editor
. That is, you create a tableview, designate how the cells will be displayed using tableviewcell, and then fill the table with data, rather than throwing it in tableviewcell
Read any tutorial on uitableview

G
gleb_kudr, 2013-10-08
@gleb_kudr

The fact is that all the cells that you write are actually templates. To show them in the TableView, you need to hook up a datasource to it in the code, where there will already be methods to call the Y template for cell number X and fill it with such and such data. This is an extremely typical pattern for lists and tables, and not only on iOS.

N
NahashSVB, 2013-10-10
@NahashSVB

In Apple, everything is well documented ( UITableView Class Reference ), as for me. If you do not understand - write, I will help. I started developing for iOS not so long ago - I had the same problems.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question