Actions, ActionCatalog, Configuration Files, etc

Topics: CAB & Smart Client Software Factory
Jun 5, 2007 at 8:17 PM
Edited Jun 5, 2007 at 8:17 PM
I've been using Actions in the same way they are used in the BankBranch reference app. Initially I had created my own ActionCondition class that would return true if the current user was an administrator. This worked fine until I needed support for different roles. I then looked into using the Configuration file based approach via EnterpriseLibraryAuthorizationActionCondition. This also works well, although I have some questions:

1) Is it possible to define rules in module configuration files? I haven't been able to find a way to do this and defining all the rules in the shell app.config doesn't seem very CAB to me. I tried registering an additional EnterpriseLibraryAuthorizationActionCondition in my Module's Module class, but this upset the ActionCatalog as it does not appear to allow duplicate ActionConditions. I thought about creating a new ActionCatalog for each module and registering my EnterpriseLibraryAuthorizationActionCondition but then I woudn't have access to the parent, a top level ActionCatalog.
So my question is: Using EnterpriseLibraryAuthorizationActionCondition hwo do we define rules at the module level?

2) Why use "Actions", why not just check CanExecute()? - I found myself mindlessly following the BankBranch example and creating an Action for each operation I wanted to control execution based on role. Then I thought: Why not just check if we CAN execute, then run the code we want and skip the whole Action altogether.
For example:
    //  Constants.cs
    public const string ShowCreateBuildOrderCommand = "ShowCreateBuildOrderCommand";
 
    //  BuildOrderTaskViewPresenter.cs
    public override void OnViewReady()
   {
        base.OnViewReady();
 
        IActionCatalogService actionCatalog = WorkItem.Services.Get<IActionCatalogService>();
        if(actionCatalog.CanExecute(ActionNames.ShowCreateBuildOrderCommand))
        {
            LinkLabel link = new LinkLabel();
            link.Text   = "Create Build Order";
            link.Margin = new Padding(10);
            link.Click += delegate { this.CreateBuildOrder(); };
            View.TaskPanel.Controls.Add(link);
        }
    }

Is there a reason I should execute the above code wrapped in an Action?
Example:
[Action(ActionNames.ShowCreateBuildOrderCommand )]
public void ShowCreateBuildOrderCommand Action(object caller, object target)
{
    LinkLabel link = new LinkLabel();
    link.Text   = "Create Build Order";
    link.Margin = new Padding(10);
 
    //  This code would need to be changed of course...
    link.Click += delegate { this.CreateBuildOrder(); };
    View.TaskPanel.Controls.Add(link);
}

I'm really curious what you all think about this. I'm about to start a major refactoring pass and don't want to start until I have some of these questions sorted out.

Thanks for reading,
Steve
Jan 18, 2008 at 6:18 PM
Hi Steve,

Did you get anywhere with this? I'm also interested in using separate config files for each module to specify Action catalog rules.

I haven't looked too closely, but is it possible to use the FileConfigurationSource to load the config file for the current module, and then use it to create a new instance of the EntLib AuthorizationProvider. You could then register that in the ActionCatalog service.

My next thought, is if you specify rules in a config file, there needs to be some encryption on that to prevent a user from modifying it, or alternatively embedding it in the assembly?
Jan 24, 2008 at 8:07 AM
Hey Winger,

NO, I haven't done anything with this and I still need to.

I just spent the last 2 hours digging around the EntLib source trying to figure out where exactly they are loading the role info from the config file. It nearly made my head explode. Too many factories, too much abstraction for my little brain. Maybe if I run it in debug and step through code I would get further, but just chasing the source gave me the definite feeling that it won't be simple to change the current behavior.

I will probably create my own IActionProvider and register an instance with each module. Haven't really thought about it too much but I will and I will post more tomorrow after I experiment.
Jan 24, 2008 at 8:08 AM
Edited Jan 24, 2008 at 8:08 AM
Duplicate post, sorry, can someone remove please?
Jan 24, 2008 at 8:34 AM

Winger300 wrote:
Hi Steve,

Did you get anywhere with this? I'm also interested in using separate config files for each module to specify Action catalog rules.

I haven't looked too closely, but is it possible to use the FileConfigurationSource to load the config file for the current module, and then use it to create a new instance of the EntLib AuthorizationProvider. You could then register that in the ActionCatalog service.

My next thought, is if you specify rules in a config file, there needs to be some encryption on that to prevent a user from modifying it, or alternatively embedding it in the assembly?


Couple more things I've learned:
You can't register the same IActionCondition twice. I was thinking that I could create my own IActionCondition that would read the configuration file (or something else) for each module, then register it with the action catalog. The current ActionCatalogService throws an exception if you add the same type twice.

My next thought was to create an IActionCondition that has a hash of actions and rules, very similar to the EntLib IAuthorizationProvider. I was thinking that I could register this single ActionCondition in my Infrastructure.Module project, then get a reference to it in each module and add my additional action/rule pairs. This would essentially result in the same structure as defining all the rules in the shell's config but would allow me to define module specific rules at the module level.
There is no method to get a IActionCondition reference from the ActionCatalog so this idea is out (without modifying the source which I would rather not do)

What's odd is that from a quick look at the implementation of the ActionCatalogService there is no reason it couldn't support multiple instances of the same IActionCondition.

eh... Gonna sleep on it, let me know if you have any ideas.

-Steve
Jan 24, 2008 at 11:45 AM
Is it not possible to get a new instance of the ActionCatalog in each module? Then you can register each IActionCondition in it's own instance of the ActionCatalogService.
Jan 24, 2008 at 4:02 PM

Winger300 wrote:
Is it not possible to get a new instance of the ActionCatalog in each module? Then you can register each IActionCondition in it's own instance of the ActionCatalogService.


This post may help: http://weblogs.asp.net/bsimser/archive/2007/10/26/taming-the-actioncatalog-in-scsf.aspx