/// <summary>
        /// Allows or blocks the display of a dropdownlist depending on user authorization level.
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="selectList"></param>
        /// <param name="optionLabel"></param>
        /// <param name="fieldRequiredPrivilege">Privilege needed to show the field</param>
        /// <param name="readOnlyBehaviour">Behavior of the field if not authorized</param>
        /// <param name="linkRequiredPrivilege">Privilege needed to navigate to the link destination</param>
        /// <param name="linkAuthFailedBehaviour">Behavior of the link text if not authorized</param>
        /// <param name="actionName">Action destination of the link</param>
        /// <param name="controllerName">Controller destination of the link</param>
        /// <param name="routeValues">Route values of the link</param>
        /// <param name="htmlAttributes"></param>
        /// <param name="forceReadOnly">Force the field into read-only mode regardless of authorization</param>
        /// <returns></returns>
        public static IHtmlContent DropDownListForAuth <TModel, TProperty>(this IHtmlHelper <TModel> htmlHelper, Expression <Func <TModel, TProperty> > expression, IEnumerable <SelectListItem> selectList, string optionLabel, Enumerations.Role fieldRequiredPrivilege, Enumerations.ReadOnlyBehaviour readOnlyBehaviour, Enumerations.Role?linkRequiredPrivilege, Enumerations.AuthFailedBehaviour?linkAuthFailedBehaviour, string actionName, string controllerName, object routeValues, object htmlAttributes, bool forceReadOnly = false)
        {
            // If user has no privileges refuse access
            bool   fullAccess = !forceReadOnly && new UserSessionContext(htmlHelper.GetHttpContext()).UserHasAccess(fieldRequiredPrivilege);
            string controlId  = htmlHelper.GetControlId(expression);

            string html = htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes).ToString();

            if (!fullAccess)
            {
                var selected = selectList.Where(x => x.Selected).FirstOrDefault();

                switch (readOnlyBehaviour)
                {
                case Enumerations.ReadOnlyBehaviour.Disabled:
                    var htmlOptions = new RouteValueDictionary(htmlAttributes);

                    if (!htmlOptions.ContainsKey("disabled"))
                    {
                        htmlOptions.Add("disabled", "disabled");
                    }
                    else
                    {
                        htmlOptions["disabled"] = "disabled";
                    }

                    html  = htmlHelper.DropDownList(controlId + "__ddl", selectList, optionLabel, htmlOptions).ToString();
                    html += htmlHelper.HiddenFor(expression).ToString();
                    break;

                case Enumerations.ReadOnlyBehaviour.EmptyString:
                    html = htmlHelper.HiddenFor(expression).ToString();
                    break;

                case Enumerations.ReadOnlyBehaviour.InnerHtml:
                    html  = htmlHelper.Span(selected == null ? "" : selected.Text, htmlAttributes).ToString();
                    html += htmlHelper.HiddenFor(expression).ToString();
                    break;

                case Enumerations.ReadOnlyBehaviour.AuthorizationLink:
                    if (!linkAuthFailedBehaviour.HasValue || !linkRequiredPrivilege.HasValue)
                    {
                        throw new ArgumentNullException("linkAuthFailedBehaviour", "linkAuthFailedBehaviour or linkRequiredPrivilege cannot be null");
                    }
                    html  = htmlHelper.ActionLinkAuth(linkRequiredPrivilege.Value, linkAuthFailedBehaviour.Value, selected == null ? "" : selected.Text, actionName, controllerName, routeValues, htmlAttributes, null).ToString();
                    html += htmlHelper.HiddenFor(expression).ToString();
                    break;

                default:
                    throw new ArgumentOutOfRangeException("readOnlyBehaviour");
                }
            }

            return(new HtmlString(html));
        }
        /// <summary>
        /// Allows or blocks the display of a textbox depending on user authorization level.
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression"></param>
        /// <param name="fieldRequiredPrivilege">Privilege needed to show the field</param>
        /// <param name="readOnlyBehaviour">Behavior of the field if not authorized</param>
        /// <param name="linkRequiredPrivilege">Privilege needed to navigate to the link destination</param>
        /// <param name="linkAuthFailedBehaviour">Behavior of the link text if not authorized</param>
        /// <param name="actionName">Action destination of the link</param>
        /// <param name="controllerName">Controller destination of the link</param>
        /// <param name="routeValues">Route values of the link</param>
        /// <param name="htmlAttributes"></param>
        /// <param name="forceReadOnly">(Optional) Force the field into read-only mode regardless of authorization</param>
        /// /// <param name="formatString">(Optional) String used to format the value of the control</param>
        /// <returns></returns>
        public static IHtmlContent TextBoxForAuth <TModel, TProperty>(this IHtmlHelper <TModel> htmlHelper, Expression <Func <TModel, TProperty> > expression, Enumerations.Role fieldRequiredPrivilege, Enumerations.ReadOnlyBehaviour readOnlyBehaviour, Enumerations.Role?linkRequiredPrivilege, Enumerations.AuthFailedBehaviour?linkAuthFailedBehaviour, string actionName, string controllerName, object routeValues, object htmlAttributes, string formatString = null, bool forceReadOnly = false)
        {
            // If user has no privileges refuse access
            bool fullAccess = !forceReadOnly && new UserSessionContext(htmlHelper.GetHttpContext()).UserHasAccess(fieldRequiredPrivilege);

            string controlId = htmlHelper.GetControlId(expression);

            ModelExpression modelExpression = htmlHelper.GetModelExpressionProvider().CreateModelExpression(htmlHelper.ViewData, expression);

            var    expressionValue = modelExpression.Model;
            string stringValue     = expressionValue == null ? "" : expressionValue.ToString();

            if (formatString != null)
            {
                stringValue = string.Format(formatString, expressionValue);
            }

            string html = htmlHelper.TextBox(controlId, stringValue, htmlAttributes).ToString();

            if (!fullAccess)
            {
                switch (readOnlyBehaviour)
                {
                case Enumerations.ReadOnlyBehaviour.Disabled:
                    var htmlOptions = new RouteValueDictionary(htmlAttributes);

                    if (!htmlOptions.ContainsKey("disabled"))
                    {
                        htmlOptions.Add("disabled", "disabled");
                    }
                    else
                    {
                        htmlOptions["disabled"] = "disabled";
                    }

                    html  = htmlHelper.TextBox(controlId + "__text", stringValue, htmlOptions).ToString();
                    html += htmlHelper.HiddenFor(expression).ToString();
                    break;

                case Enumerations.ReadOnlyBehaviour.EmptyString:
                    html = htmlHelper.HiddenFor(expression).ToString();
                    break;

                case Enumerations.ReadOnlyBehaviour.InnerHtml:
                    html  = htmlHelper.SpanFor(expression, htmlAttributes, formatString).ToString();
                    html += htmlHelper.HiddenFor(expression).ToString();
                    break;

                case Enumerations.ReadOnlyBehaviour.AuthorizationLink:
                    if (!linkAuthFailedBehaviour.HasValue || !linkRequiredPrivilege.HasValue)
                    {
                        throw new ArgumentNullException("linkAuthFailedBehaviour", "linkAuthFailedBehaviour or linkRequiredPrivilege cannot be null");
                    }
                    html  = htmlHelper.ActionLinkAuth(linkRequiredPrivilege.Value, linkAuthFailedBehaviour.Value, stringValue, actionName, routeValues, htmlAttributes).ToString();
                    html += htmlHelper.HiddenFor(expression).ToString();
                    break;

                default:
                    throw new ArgumentOutOfRangeException("readOnlyBehaviour");
                }
            }

            return(new HtmlString(html));
        }