web-dev-qa-db-fra.com

Remplacer AuthorizeCore dans l'attribut personnalisé Authorize entraîne l'erreur "Aucune méthode appropriée trouvée pour remplacer"

J'essaie de créer un AuthorizeAttribute personnalisé. Ainsi, dans mon projet Core (une bibliothèque de classes), j'ai le code suivant:

using System;
using System.Web;
using System.Web.Mvc;
using IVC.Core.Web;
using System.Linq;

namespace IVC.Core.Attributes
{
    public class TimeShareAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if(!httpContext.Request.IsAuthenticated)
                return false;

            var rolesProvider = System.Web.Security.Roles.Providers["TimeShareRoleProvider"];

            string[] roles = rolesProvider.GetRolesForUser(httpContext.User.Identity.Name);

            if(roles.Contains(Website.Roles.RegisteredClient, StringComparer.OrdinalIgnoreCase))
            {
                return true;
            }

            return false;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectResult("/TimeShare/Account/LogOn");

            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

Lorsque j'essaie de construire la chose, j'obtiens cette erreur: Erreur 2 'IVC.Core.Attributes.TimeShareAuthorizeAttribute.AuthorizeCore (System.Web.HttpContextBase)': aucune méthode appropriée trouvée pour remplacer ...

Est-ce que j'ai râté quelque chose? J'ai cherché partout, mais chaque site que je peux trouver me dit simplement de faire exactement ce que j'ai fait ici. J'utilise mvc2 btw.

  • Modifié pour ajouter: si je déplace la classe vers le projet MVC dans la même solution, il n'y a pas d'erreur de compilation.
28
JoseMarmolejos

Oui, j'ai aussi essayé de trouver celui-ci pendant un moment et je l'ai compris depuis le navigateur d'objets. Ce n'est certainement pas clair dans les documents MSDN, sauf si vous faites défiler jusqu'au commentaire de l'utilisateur sur la classe HttpContextBase. Et, bien sûr, de nombreux exemples sur le Web, mais personne ne montre jamais le fichier de classe complet! :)

Essayez d’ajouter une référence à System.Web.Abstractions à votre projet.

MISE À JOUR: Le MSDN vient de signaler que sous la version 3.5, il se trouve sous System.Web.Abstractions, mais sous la version 4, il se trouve sous System.Web.

30
alphadogg

Voici AuthorizationAttribute.cs

/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/

namespace System.Web.Mvc {
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq;
    using System.Security.Principal;
    using System.Web;

[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "Unsealed so that subclassed types can set properties in the default constructor or override our behavior.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter {

        private string _roles;
        private string[] _rolesSplit = new string[0];
        private string _users;
        private string[] _usersSplit = new string[0];

        public string Roles {
            get {
                return _roles ?? String.Empty;
            }
            set {
                _roles = value;
                _rolesSplit = SplitString(value);
            }
        }

        public string Users {
            get {
                return _users ?? String.Empty;
            }
            set {
                _users = value;
                _usersSplit = SplitString(value);
            }
        }

        // This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
        protected virtual bool AuthorizeCore(HttpContextBase httpContext) {
            if (httpContext == null) {
                throw new ArgumentNullException("httpContext");
            }

            IPrincipal user = httpContext.User;
            if (!user.Identity.IsAuthenticated) {
                return false;
            }

            if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) {
                return false;
            }

            if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) {
                return false;
            }

            return true;
        }

        private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        public virtual void OnAuthorization(AuthorizationContext filterContext) {
            if (filterContext == null) {
                throw new ArgumentNullException("filterContext");
            }

            if (AuthorizeCore(filterContext.HttpContext)) {
                // ** IMPORTANT **
                // Since we're performing authorization at the action level, the authorization code runs
                // after the output caching module. In the worst case this could allow an authorized user
                // to cause the page to be cached, then an unauthorized user would later be served the
                // cached page. We work around this by telling proxies not to cache the sensitive page,
                // then we hook our custom authorization code into the caching mechanism so that we have
                // the final say on whether a page should be served from the cache.

                HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
            }
            else {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }

        // This method must be thread-safe since it is called by the caching module.
        protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) {
            if (httpContext == null) {
                throw new ArgumentNullException("httpContext");
            }

            bool isAuthorized = AuthorizeCore(httpContext);
            return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest;
        }

        internal static string[] SplitString(string original) {
            if (String.IsNullOrEmpty(original)) {
                return new string[0];
            }

            var split = from piece in original.Split(',')
                        let trimmed = piece.Trim()
                        where !String.IsNullOrEmpty(trimmed)
                        select trimmed;
            return split.ToArray();
        }

    }
}
23
mft2010

De plus, comme je l'ai déjà vu auparavant, veillez à ce que Visual Studio ajoute automatiquement des utilisations pour vous. Si vous ne faites pas attention, vous pouvez finir par ajouter System.Web.Http au lieu de System.Web.Mvc.

8
costr

Lorsque j'ai copié mes anciens codes dans mon nouveau projet, le même problème s'est posé. 

Il s'est avéré qu'il existe 2 AuthrizeAttributes. L'un se trouve dans System.Web.Mvc et un autre dans System.Web.Http . Le premier a le AuthrizeCore, tandis que l'autre ne l'a pas.

Vous devrez peut-être ajouter une référence à System.Web.Mvc pour accéder au droit.

2
cheny

J'ai aussi eu cette erreur. Il s’est avéré que Visual Studio avait ajouté à mon ActionFilter par défaut:

using System.Web.Http;

Même quand j'ai ajouté System.Web.Mvc, j'ai toujours eu l'erreur. Commenter System.Web.Http et simplement utiliser System.Web.Mvc semble résoudre le problème pour moi. 

En espérant que cela puisse aider quelqu'un!

2
GrahamJ

Utilisez l'espace de noms System.Web.Mvc.

Exemple de code:

using System.Web.Mvc;

public class CustomAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
    {
        var service = new AuthService();
        return service.GetCurrentUser() != null;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
    }
}
1
ddagsan

Sous fw v4.5, il apparaît maintenant sous System.Web.Mvc.

0
Matthew Moody