Async BusinessRule Error - CSLA 4

Async BusinessRule Error - CSLA 4

Old forum URL: forums.lhotka.net/forums/t/9744.aspx


JJLoubser posted on Thursday, November 11, 2010

This is executing, but the context never Completes and the red indicator that show the error on xaml is not working, do we miss something?

 

 protected override void AddBusinessRules()
        {
            base.AddBusinessRules();

            BusinessRules.AddRule(new CheckUserLogonName(UsernameProperty, new List<Csla.Core.IPropertyInfo> { MaySignInProperty, UserIDProperty }));
            BusinessRules.AddRule(new CheckUserLogonName(MaySignInProperty, new List<Csla.Core.IPropertyInfo> { UsernameProperty, UserIDProperty }));

                }

private class CheckUserLogonName : Csla.Rules.BusinessRule
        {
            public CheckUserLogonName(Csla.Core.IPropertyInfo primaryProperty, List<Csla.Core.IPropertyInfo> affectedProperties)
              : base(primaryProperty)
            {
                IsAsync = true;
             
                InputProperties = new List<Csla.Core.IPropertyInfo> { PrimaryProperty };

                foreach (var prop in affectedProperties)
                {
                    AffectedProperties.Add(prop);
                    InputProperties.Add(prop);
                }
               
            }

            protected override void Execute(Csla.Rules.RuleContext context)
            {
                 if ((bool)context.InputPropertyValues[MaySignInProperty])
                    {
                        var dp = new DataPortal<CheckUserLogonNameCO>();
                        dp.ExecuteCompleted += (o, e) =>
                        {
                            if (e.Error != null)
                            {
                                context.AddErrorResult(e.Error.Message);
                                context.Complete();
                            }
                            else
                            {
                                if (e.Object.Exists)
                                {
                                    context.AddErrorResult("This username already exist");
                                    context.Complete();
                                }
                               
                            }
                           
                        };
                        dp.BeginExecute(new CheckUserLogonNameCO((int)context.InputPropertyValues[UserIDProperty], (string)context.InputPropertyValues[UsernameProperty]));  //this does work and exec
                    }                   
            }
        }

 

- xaml is fine with a propertystatus

 

JonnyBee replied on Thursday, November 11, 2010

Every code execution path in an async rules Execute must call Context.Complete. 

     protected override void Execute(Csla.Rules.RuleContext context)
            {
                 if (!(bool)context.InputPropertyValues[MaySignInProperty])
                 {
                       context.Complete;
                       return();
                 }

                 var dp = new DataPortal<CheckUserLogonNameCO>();
                 dp.ExecuteCompleted += (o, e) =>
                  {
                       if (e.Error != null)
                       {
                           context.AddErrorResult(e.Error.Message);
                           context.Complete();
                           return:
                       }

                       if (e.Object.Exists)
                        {
                            context.AddErrorResult("This username already exist");
                        }

                         // must call context.Complete
                         context.Complete();   
                            
                        }
                
                   };
                   dp.BeginExecute(new CheckUserLogonNameCO((int)context.InputPropertyValues[UserIDProperty], (string)context.InputPropertyValues[UsernameProperty]));  //this does work and exec
                    }     
            }

JJLoubser replied on Wednesday, January 05, 2011

thanks for the answer and this post:

http://forums.lhotka.net/forums/t/9911.aspx

we are still trying to get our error and the place where we do not set the context.Complete or should not set it. the system thinks it is not complete while it is.

JonnyBee replied on Wednesday, January 05, 2011

Hi JJ,

I'd  suggest that you create async factory methods on your CommandObjects as that will simplify the code in your rule and place responsibility where it shuld be.

Ex in CheckUserLogonNameCO:

public static void BeginExecute(int userid, string username, EventHandler<DataPortalResult<CheckUserLogonNameCO>> callback)
{
    var obj = new CheckUserLogonNameCO(int userid, string username)
    DataPortal.BeginExecute(obj, callback);
}

And your rules Execute method:
protected override void Execute(Csla.Rules.RuleContext context)
            {

                 if (!(bool)context.InputPropertyValues[MaySignInProperty])
                 {
                        // should set error???
 
                       context.Complete();   // must call context complete to say rule is finished.
                       return();
                 }

                 // start async call - must call context.Complete in callback
                 CheckUserLogonNameCO.BeginExecute((int)context.InputPropertyValues[UserIDProperty],
                                                                                 (string)context.InputPropertyValues[UsernameProperty],
                                                                                 // callback
                                                                                 (o, e) => {
                                                                                                 if (e.Error != null)
                                                                                                 {
                                                                                                      context.AddErrorResult(e.Error.Message);
                                                                                                 }

                                                                                                 else if (e.Object.Exists)
                                                                                                 {
                                                                                                     context.AddErrorResult("This username already exist");
                                                                                                  }

                                                                                                  // must call context.Complete
                                                                                                  context.Complete();   
                            
                                                                                                });
                
                    }     

I find this style of coding will make it easier to read your code and understand the execution flow.

PS! Try without setting the AffectedProperties (as you are not using OutputValues/AddOutValue and this is an Async rule).  And try the sync Depency rule instead (or as an alternative) to check if this helps.

JJLoubser replied on Monday, January 17, 2011

Cannot mix async and sync Auth Properties Normal 0 false false false EN-ZA X-NONE X-NONE MicrosoftInternetExplorer4

Answer. It is a bug: http://forums.lhotka.net/forums/p/9552/46611.aspx#46611

 

Copyright (c) Marimer LLC