interface IControllerAccessChecker
void CheckAccess(documentIds)
interface IControllerAccessCheckerFactory
IControllerAccessChecker Create()
class TransactionControllerAttribute
string TransactionIdParameter
class PublicControllerAttribute
class ControllerAccessCheckerFactory : IControllerAccessCheckerFactory
ControllerAccessCheckerFactory(IActionContextAccessor actionContextAccessor) {...}
IControllerAccessChecker Create()
var context = actionContextAccessor.ActionContext;
var actionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
var transactionControllerAttribute = actionDescriptor.ControllerTypeInfo.GetCustomAttributes<TransactionControllerAttribute>().SingleOrDefault();
if (transactionControllerAttribute != null)
var transactionId = (Guid)context.RouteData.Values[transactionControllerAttribute.TransactionIdParameter];
var jobId = (Guid)context.RouteData.Values[transactionControllerAttribute.JobIdParameter];
return new TransactionControllerAccessChecker(transactionId, jobId)
var publicControllerAttribute = actionDescriptor.ControllerTypeInfo.GetCustomAttributes<PublicControllerAttribute>().SingleOrDefault();
if (publicControllerAttribute != null)
return new PublicControllerAccessChecker()
throw new InvalidOperationException("Mark the controller with either TransactionControllerAttribute or PublicControllerAttribute");
class DocumentsControllerBase
protected DocumentsControllerBase(IControllerAccessCheckerFactory accessCheckerFactory) {...}
void SomeAction(documentIds)
_accessCheckerFactory.Create().CheckAccess(documentIds)
class PublicDocumentsController : DocumentsControllerBase
public PublicDocumentsController(IControllerAccessCheckerFactory accessCheckerFactory)
: base(accessCheckerFactory) {}
[Route("api/transactions/{transactionId}/jobs/{jobId}/documents")]
[TransactionController(TransactionIdParameter = "transactionId", JobIdParameter = "jobId")]
class TransactionsDocumentsController : DocumentsControllerBase
public TransactionsDocumentsController(IControllerAccessCheckerFactory accessCheckerFactory)
: base(accessCheckerFactory) {}