2

I have a transaction attribute that performs a commit in the onactionexecuted method.

This is specified at the controller method, for one of my actions i need to override that method and not call the code in onactionexecuted?

Here is some sample code.

[Transaction]
public class TestController
{
    public ActionResult Index()
    {
        return View();
    }

    [NoTransaction]
    public ActionResult Test()
    {
        return View();
    }
}

The [NoTransaction] attribute should override the onactionexecuted method in [Transaction]. Is there a way to do this?

1
  • 1
    Please provide some code to illustrate your question. Commented Jan 12, 2010 at 23:52

3 Answers 3

4

All action filters have an order property. If it's not defined, it has an implicit value of -1. When filters have the same order, the order is determined by scope: is it applied to a controller or applied to an action.

Controller scoped filters of the same order run before action filters of the same order.

The simple workaround is to apply an explicit ordering in this case to the Transaction attribute.

[Transaction(Order=1)]
public class TestController
{
    public ActionResult Index()
    {
        return View();
    }

    [NoTransaction(Order=0)]
    public ActionResult Test()
    {
        return View();
    }
}

This will ensure that NoTransaction runs before Transaction does.

If you want NoTransaction to override Transaction, the simplest thing to do is to have NoTransaction add some special key in HttpContext.Items which the Transaction attribute reads. The presence of this key would tell the Transaction attribute to not do anything.

Sign up to request clarification or add additional context in comments.

Comments

3

If your NoTransactionAttribute is a filter, you can set a flag within its OnActionExecuting() as suggested in the other post. Otherwise:

// just a marker attribute with no special logic
public sealed class NoTransactionAttribute : Attribute { }

public class TransactionAttribute : ActionFilterAttribute {
    public override void OnActionExecuted(ActionExecutedContext filterContext) {
        if (filterContext.ActionDescriptor.IsDefined(typeof(NoTransactionAttribute), true /* inherit */)
            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(NoTransactionAttribute), true /* inherit */) {
                return; // should skip logic
        }

        // perform your logic here
    }
}

1 Comment

It sucks that ActionDescriptor.IsDefined(typeof(Foo),true) doesn't actually use inheritance correctly. E.g. the Controller has [Authorize], which is inherited by the Action, but the method ActionDescriptor.IsDefined returns false.
0

In the NoTransaction attribute's OnActionExecuting you could put some sort of a flag in HttpContext.Items which you can then check for in the Transaction attribute's OnActionExecuted. Or some variation on that.

HTHs,
Charles

2 Comments

Does the [NoTransaction] run first?
I think the order will be: Transaction.OnActionExecuting -> NoTransaction.OnActionExecuting -> NoTransaction.OnActionExecuted -> Transaction.OnActionExecuted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.