Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding AuthorizeCore in custom Authorize attribute results in "no suitable method found to override" error

I'm trying to build custom AuthorizeAttribute, so in my Core project (a class library) I have this code:

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);         }     } } 

When I try to build the thing I get this error: Error 2 'IVC.Core.Attributes.TimeShareAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase)': no suitable method found to override ...

Am I missing something here? I've searched all over but every site I can find just tells me to do exactly what I did here. I'm using mvc2 btw.

  • Edited to add: if I move the class to the mvc project in the same solution there's no compiler error.
like image 749
JoseMarmolejos Avatar asked Aug 15 '10 17:08

JoseMarmolejos


2 Answers

Yeah, I fumbled with that one for a while too and figured it out from the Object browser. It certainly is NOT clear from the MSDN docs unless you scroll all the way down to the user comments on the HttpContextBase class. And, of course, lots of examples on the web, but nobody ever shows the full class file! :)

Try adding a reference to System.Web.Abstractions to your project.

UPDATE: Just noticed from the MSDN that under v3.5, it is under System.Web.Abstractions, but under v4, it's under System.Web.

like image 171
alphadogg Avatar answered Sep 19 '22 08:09

alphadogg


Here is 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();         }      } } 
like image 20
mft2010 Avatar answered Sep 21 '22 08:09

mft2010