Async Lazy Load of BusinessListBase subclass in Silverlight

Async Lazy Load of BusinessListBase subclass in Silverlight

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


KevinKlasman posted on Monday, March 29, 2010

Now that I've got anonymous delagates working, I'm still having trouble async lazy loading a BusinessListBase derived BO.

I'm using VS201 beta 2, SL4 beta, CSLA 3.8.2, Windows7 Pro.

The app is similar to a Windows explorer app, with a treeview of folders (EditableRootListBase). Each folder has a collection of SubFolders (BusinessListBase). I intiially tried making the sub folders just a child collection of the top level folder, but ultimately decided these are different objects.

In another post on this site, Rocky said there's a perfectly good async lazy load pattern, and I think I'm using it, but it still blows up.

When the user clicks a top level folder for the first time, I want to load the child collection of subfolders. Simply accessing the folder.SubFolders property should cause the collection to load.

        void MainTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            Intellifolder folder = MainTreeView.SelectedItem as Intellifolder;
            if (folder != null)
            {
                if (folder.SubFolders == null)
                {
                       // To do...something
                }
            }
        }

       private static PropertyInfo<SubFolders> SubFoldersProperty = RegisterProperty<SubFolders>(c => c.SubFolders);
       public SubFolders SubFolders
       {
           get
           {
               if (!FieldManager.FieldExists(SubFoldersProperty))
               {
                   if (this.IsNew)
                   {
                       //LoadProperty(SubFoldersProperty, Intellifolders.NewIntellifolder());
                   }
                   else
                   {
                       //LoadProperty<SubFolders>(SubFoldersProperty, SubFolders.GetSubFolders(this));
                       SubFolders.GetSubFolders(this, (o, e) =>
                           {
                               if (e.Error == null && e.Object != null)
                               {
                                   // process result
                               }
                           });
                   }
               }
           }
           set { SetProperty(SubFoldersProperty, value); }
       }

        public static void GetSubFolders(Intellifolder parent, EventHandler<DataPortalResult<SubFolders>> handler)
        {
            DataPortal<SubFolders> dp = new DataPortal<SubFolders>();
            dp.FetchCompleted += handler;
            dp.BeginFetch(new SubFolderCriteria(_userGuid, parent.NodeID));
        }

#if !SILVERLIGHT
        #region Data Access

        private void DataPortal_Fetch(SubFolderCriteria criteria)
        {
            // TODO: load values into object
            Guid userGuid = criteria.UserGuid;
        }
#endif

I never get to DataPortal_Fetch. Stepping through the code, it throws an error when I try to step into method.DynamicInvoke(arguments) in SynchronizedWcfProxy.RunSynchronized. Its an "Unhandled Error in ... Silverlight App. Code 4004, ManagedRuntimeError. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. --> "

And that's all I can get from this error that was displayed in the VS JIT debugger as clicking yes on this dialog says it cannot attach to the process since its already attached by another debugger.

Thanks, Kevin

 

RockfordLhotka replied on Monday, March 29, 2010

A couple questions.

First, why are you using SynchronizedWcfProxy? That exists purely to support some of our internal unit testing scenarios and isn't intended for use in any real app. It is actually counter-productive in a real app, because it specifically blocks the use of multiple async operations, which I can't imagine anyone actually wanting in a real app.

Second, have you tested calling GetSubFolders() directly to make sure it works independently from lazy loading? This is the sort of scenario where unit testing comes in handy - make sure the lowest level operations are working before trying to assemble them into more complex operations.

KevinKlasman replied on Monday, March 29, 2010

You mean SynchronizedWcfProxy is not required by Silverlight? Since its in a least some of the SL samples (I haven't looked at all of them in this regard) I assumed that it was required. Adding that was one of many changes I made to me code that eventually got it working...although I have no idea whether it was needed or not. What should I use it its stead? Just comment out that line of code?

No I haven't unit tested the code...the base pattern seems so standard that it seems like a no-brainer to work (I know, I just labeled myself a no-brainer :)

I fully support unit testing, but I'm just building an evaluation application, and do I remember correctly that the CSLA 3.8.2 doesn't really support unit testing via VS 2010, at least in its current form? Or is that just for the SL UI piece?

I'll take a shot at unit testing this code, since I know its good for me...don't get me wrong, I'm a big proponent of unit testing. 

I take it then that you see no obvious errors in my approach.

 

 

 

RockfordLhotka replied on Monday, March 29, 2010

The default proxy is WcfProxy, so if you are using WCF to talk to the server that should be automatic - as long as you have the config set up in clientconfig.

In pre-release versions of SL2 there were some issues with WCF that made SynchronizedProxy necessary, and I suppose some of that code is still in some samples, sorry.

Testing of SL code can be challenging because of the async server calls. Technically that's probably not "unit testing" because you are talking to a server, but it is meaningful still even if it is "integration testing".

You can use the VS10 Silverlight unit test support - you just need to write your tests using their async testing pattern.

The problem I personally face is that I want the exact same test code in SL and .NET, and the Microsoft tools don't provide that. Which is why the CSLA tests use UnitDriven, which does enable the same test code in SL and .NET. And you can use UnitDriven too if you'd like - we donated it to the community via CodePlex so people who find it useful can freely use it.

KevinKlasman replied on Monday, March 29, 2010

After trying all afternoon, I have no idea how to unit test an async factory method. Or what tools to use. UnitDriven seems to only work with NUnit, which doesn't seem to work with .NET 4. At least I can find no coherent examples of this on the web. NUnit's blog hasn't been updated in a year...are they gone?

So could someone post a simple unit test project for testing an SL4, async factory method? I would prefer a VS2010 example, not an NUnit example, but if you've got an NUnit example that works with .NET 4, SL4, CSLA 3.8.2 than I'll take that.

        public static void GetUser(string userName, EventHandler<DataPortalResult<ClxUser>> callback)
        {
            var dp = new DataPortal<ClxUser>();
            dp.FetchCompleted += callback;
            dp.BeginFetch(new SingleCriteria<ClxUser, string>(userName));
        }

Thanks...Kevin (hoping the CSLA for SL video will make all of this clear...can't wait to get it).

RockfordLhotka replied on Monday, March 29, 2010

UnitDriven on SL is self-contained. Look at the SL tests for Silverlight - specifically the actual test app, which executes the UnitDriven shell.

UnitDriven works on the .NET side as simply an extra DLL you use in your tests. It works with nunit or mstest. The CSLA 4 tests use UnitDriven and are now running in mstest - though I'm told there is a version of nunit for .NET 4 now too, but I couldn't wait.

KevinKlasman replied on Tuesday, March 30, 2010

I downloaded the Csla 4 Preview. The csla.silverlight.test solution (csla.silverlight project) won't build because the BrowseableAttribute could not be found, which is interesting, since it's available in .NET 3.5 and .NET 4 according to MSDN. What are the system requirements for Csla 4 Preview? I'm using VS2010 Beta 2, SL4 beta.

Error 1 The type or namespace name 'BrowsableAttribute' could not be found (are you missing a using directive or an assembly reference?). My system.dll reference is set to C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\system.dll... should it be something else?

Anyway, I don't see anything that looks like "the actual test app". I must be blind...or looking in the wrong place. What project in which solution?

The samples for Csla 4 Preview look to be unchanged from 3.8.2...is that true?

 

RockfordLhotka replied on Tuesday, March 30, 2010

Just remove the Browsable attributes from the SL code. The preview was created using various versions of VS10, .NET 4 and SL4 and a post-Beta bit of code slipped into that preview release.

Of course now we're just a couple weeks from the VS10 launch and all the code in svn targets the RC of .NET 4 and SL4, but I haven't don't another prerelease with those bits.

The solution you want is csla.silverlight.test.sln - that has all the SL test projects. But again, you don't necessarily need all the complexity of the SL tests - I'm just suggesting you look at the SL test project itself, which is also called csla.silverlight.test.

Now that I think about it, this is the same configuration and setup as in SL3 and CSLA 3.8. The only real difference is that the SL4 one is using an updated version of UnitDriven that supports SL4. But the project and test code are the same.

It is true that we haven't updated the samples for CSLA 4 yet. It seemed like a waste of time since CSLA 4 is still changing. Once CSLA 4 stops changing so much, then we'll update at least some of the samples.

KevinKlasman replied on Tuesday, March 30, 2010

I removed that attribute and the solution compiles now and I see the test driver web page come up.

Thanks

KevinKlasman replied on Tuesday, March 30, 2010

Is there any documentation on how to create my own UnitDriven test project? Project templates? Tutorial?

There are only DLLs in the download on codeplex.

I'd rather do this in SL4/Csla 3.8.2, which is the environment my evaluation project runs in.

RockfordLhotka replied on Tuesday, March 30, 2010

Not that I know of. We donated UnitDriven to the community specifically because I don't have time to maintain another framework. I know it is used by a few other projects, and we got a nice UI upgrade through community contribution. But nobody has stepped forward to create the elements you are looking for.

KevinKlasman replied on Tuesday, March 30, 2010

I've managed to figure out what pieces to steal from the csla.silverlight.test solution how to modify those pieces, and how to structure my own solution so that I can get the UnitDriven UI to come start up and see my one test method, set a breakpoint in it and stop.

So I guess I'm on my way...although I've thought that many times before!

I'd post the steps I followed to help others, if I didn't think I did it the hard way.

Or is there only the "hard way" at this point?

Kevin

RockfordLhotka replied on Tuesday, March 30, 2010

Please share - there may only be the "hard way" Smile

Better yet, share on the UnitDriven wiki, since what you are doing probably applies more to that project than directly to CSLA.

Copyright (c) Marimer LLC