开发者

c# Attributes and overriding behavior asp.net mvc

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?


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.


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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜