Another Sample available (CoProjectDF)

Jul 24, 2011 at 10:51 PM

Hi,
Inspired by IdeaBlade's conversion of BookShelf to BookShelfDF, I've done the same with CoProject, see http://coproject.codeplex.com/

And I've gone on to add more functionality. I've placed the Zip into the patch upload area.
It's complete out of the zip - so it contains the v1.1 Caliburn.Micro dll as used by this framework, and the source of this framework is included being about a month old.
In the DB,I've changed only the User table compared to the original, so that the login/register feature will work. The SQLEXpress db is now named CoProjectDF.
Out of the Zip, it will use sample data and the xml file is present, so should work immediately it is compiled and run.
Change the code in EntityManagerProviderFactory.cs if you want to try a SQLExpress DB - mdf and ldf files are included in project root. Since I add the DB to my copy of SQLExpress, the connection strings are set for this and not an attached db. A UserName of "john" and a password of "johnjohn1!" should get you going. Passwords are not encrypted, so just look in the database.

I've found the conversion very instructive and this Devforce-CaliburnMicro framework is a great.
Hope others find it useful.

cheers
John

Coordinator
Jul 25, 2011 at 2:57 AM

John,

This is great. I would love to include this as a reference application. Something I've been wanting to do, but haven't had time yet. I had to change a few of the IdeaBlade references. "Specific Version" was set to true, so the solution didn't build against DF 6.1.1. Before I go any further, though, it doesn't seem to work right. I can login and I get a read only view of the users in the admin section, but I can't do anything else in the app. It's all read only and there's no content. Am I missing something?

Marcel

Jul 25, 2011 at 9:35 AM

Marcel,

Humm. I thought there might be teething problems, but hoped not...

I've got IB 6.1.1.1  universal installed (but I did upgrade from 6.1.1.0 when the later version came out). The DLLs are definitely 6.1.1.1
<ideablade,configuration version="6.00" /> is what is created from the IB Cosmo template into web.config.
The IB DLLs are the only stuff not in the Zip, so could the hint path pull in a different version on your machine?
Can you say more as to where, "Specific Version" is set, as it's not something I've intentionally set to true.
Needless to say mine compiles in VS2010 prof without problem !!

The only bits that "connect" to a DB are:-

1. ToDoLists (and the child ToDoItem) as Anonymous (prior to any login)
   Click on the search icon and after a loooong wait the ToDoLists will populate. Busy will go away, and then the childs appear.
  Click on any child and after a wait the child will appear in the right-hand edit pane. When connected to a real DB, you can edit and save. Delete just deletes from the view.

2. Admin is just a read-only list of the Users, but only available once you're logged in, [simple Principal check in Activate]
(this is the area of IB I was interested in and why I did the demo - I'm interested in finding out whether IB can help me with application security. For example add Interceptors etc)

3. Login and Register work. You can register a new user, and see IB's validation in the various fields. The template validation is inisting on a number and special before accepting a password, hence "johnjohn1!"
Once Registered, you then need to Login in (it isn't automatic from the Register)
Of course you need to switch away from Admin and back again to see the new user in the grid.

The remaining Home, Milestones, Messages and About, just show a View with appropriate text. In the original CoProject some did not have views, and I added some extras.

Keeping the App in-sync with various library changes will be a challenge. Already there are breaking changes in Caliburn.Micro.
But IB will be the pivot as it is the only component that needs a (free) licence code and thus a "new" person to here will only be able to get the latest version from IB.
So it does need to go under version control. I was hoping you'd add it here - but if you think it would be more convenient, it could go into a separate CodePlex project

hope you get it working
John

Jul 25, 2011 at 12:48 PM
Edited Jul 25, 2011 at 12:49 PM

Hi,
I found the "Specific Version" option and set it to false for all references in all projects. Not something that I've used before and certainly I'd not expecting any specific versions.
Must be something Visual Studio is setting. Is there a VS global  option to abide or ignore.
Looked into the .csproj files and see that my copies of your framework were set for various earlier versions of IB. I've editied those to 6.1.1.1
Noticed that I was not using or included IdeaBlade.Extensions and removed an unneeded System.ServiceModel reference.
Uploaded a new version to patches.
But, it doesn't change compile or run for me.
Let me know if this version is any better
J

Jul 25, 2011 at 1:37 PM

Hi,

1) Copied CoProjectDF.mdf & CoProjectDF_log.ldf to my sqlserver C:\Program Files (x86)\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA

2) Tested the database in MSSM

3) Built and Ran project

4) Followed instructions to press search in todo and.. It works! Oh happy days.

I will test and give my feedback.

Thanks much

John

From: jradxl [email removed]
Sent: Monday, July 25, 2011 8:49 AM
To: John R. Tomaselli
Subject: Re: Another Sample available (CoProjectDF) [devforcecaliburn:266391]

From: jradxl

Hi,
I found the "Specific Version" option and set it to false for all references in all projects. Not something that I've used before and certainly I'd not expecting any specific versions.
Must be something Visual Studio is setting. Is there a VS global option to abide or ignore.
Looked into the .csproj files and see that my copies of you framework were set for various earlier versions of IB. I've editied those to 6.1.1.1
Noticed that I was not using or included IdeaBlade.Extensions and removed an unneeded System.ServiceModel reference.
Uploaded a new version to patches.
But, it doesn't change compile or run for me.
Let me know if this version is any better
J

Jul 25, 2011 at 2:21 PM

Tested in release mode

1) Successful Admin login.

2) Successful registration of new user.

3) Successful modification of todo data.

4) Noticed inability to add data.

John

From: jradxl [email removed]
Sent: Monday, July 25, 2011 8:49 AM
To: John R. Tomaselli
Subject: Re: Another Sample available (CoProjectDF) [devforcecaliburn:266391]

From: jradxl

Hi,
I found the "Specific Version" option and set it to false for all references in all projects. Not something that I've used before and certainly I'd not expecting any specific versions.
Must be something Visual Studio is setting. Is there a VS global option to abide or ignore.
Looked into the .csproj files and see that my copies of you framework were set for various earlier versions of IB. I've editied those to 6.1.1.1
Noticed that I was not using or included IdeaBlade.Extensions and removed an unneeded System.ServiceModel reference.
Uploaded a new version to patches.
But, it doesn't change compile or run for me.
Let me know if this version is any better
J

Jul 25, 2011 at 2:55 PM

To jadxl, please send me an email on my previously published email under sample app in discussion group and I'll send you xaml code for devexpress.

Coordinator
Jul 25, 2011 at 6:59 PM

Thanks. I'll take another look. I intend to add this to the project. I'm planning on factoring out SampleApplication, HellowWorld and this into a Samples folder.

The "Specific Version" thing instructs the compiler to build with a specifc version of an assembly or accept whatever version it finds. It's a source of many confusions. It's automatically set to True if you add a reference and it effectivly locks you to the version of the assembly at the time you added the reference.

But then there's Assembly Binding Redirection http://msdn.microsoft.com/en-us/library/2fc472t2.aspx and Publisher Policies http://msdn.microsoft.com/en-us/library/dz32563a.aspx that add a whole new dimension to this. Publisher Policies is kind of the global switch you are asking for. This is what's used when Microsoft issues a Service Pack for .NET. They install policies for all assemblies, so that your code continues to compile against updated versions of the .NET assemblies. We currently don't do that with the DF assemblies, because we add/change features with every new version, so a newer version could truely be incompatible with your application.

Jul 25, 2011 at 7:23 PM

Thanks Marcel,
Look forward to seeing the "samples" folder.. Good idea

In my searching this morning I found reference to the publisher policies and I've seen binding redirection as VS offers to add it sometimes.
But having experimented I can see that manually adding a DLL, such as DevForce, was setting Specfic Version to true. And it makes sense as a compile time indication that something has changed if that version is not matched, as you say.  Hence why DevExpress (and others) give you a project upgrade utility.

I expect that the reason then, was the 6.0.8.x references that where embedded your framework projects, as I copied in the code from your SVN respository. But what's not explained is why I've never seen a compile error, and you did immediately.  But I cannot find any VS option, or any option in the PowerTools etc addons that says to ignore it. So I remain puzzeled...

Hopefully you can get it to work and complile - as JohnTom reports he can.
I need to do some other things, but in a few weeks time I will provide the WPF version of HelloWorld (which works, but is not yet finalised) and a WPF version of my CoProjectDF, which is started but not yet finished - I broke off from it as I realised I need to find out how the silverlight version worked first !!

cheers
John

 

Coordinator
Jul 25, 2011 at 10:54 PM

Ok. Got it to work. I didn't realize that only the ToDoList essentially has some functionality. Let me think about it some more. I was hoping for a more complete reference app, but this is a good start. It may be simple enough to get the idea across, but still shows the skeleton of a real app. I like that.

Coordinator
Jul 26, 2011 at 12:35 AM

Quick update. I've reorganized the solution under the Samples folder and pointed up to the libs and Supporting Projects, so it always builds against the latest version of the framework. I'm doing a code-review and clean up. I've gotten rid of IResultWrapper2. I think part of what led you to create this class is a bug that I recently fixed. As you noted it previously never came back from the yield if there was an error, even if the error was marked as handled. The OnComplete() method marks the error has handled if a onFail callback is provided.

I didn't get the point of the Result property. You can always introduce locally scope variables to hold the result, like the error variable below. So, here's how LoadData() looks now. I think that's much cleaner, don't you?

        public IEnumerable<IResult> LoadData()
        {
            using (Busy.GetTicket())
            {
                //When using DevelopmentEntityManagerProvider() the application needs an Initialisation
                // for use in Anonymous mode.
                yield return new IResultWrapper(_repository.Initialise);
 
                Exception error = null;
                yield return new IResultWrapper(
                    () => _repository.GetToDoLists("Name",
                            result => Lists = new BindableCollection<ToDoList>(result),
                            e => error = e)); // Marks error as handled, so we always come back from the yield
 
                if (error != null)
                    MessageBox.Show(error.Message, "System Error"MessageBoxButton.OK);
            }
        }
Coordinator
Jul 26, 2011 at 7:21 PM

I've done some more refactoring and clean up. I also got rid of the CoroutineWrapper. It's an interesting idea for when you don't have control of the called method, but in this case it's much easier for the method to just return an IResult.

public IResult GetToDoItem(int toDoItemID, Action onSuccess, Action<Exception> onFail)
{
    IsReadOnly = true;
 
    return new IResultWrapper(
        () => _repository.FindToDoItemByID(toDoItemID,
                                            (r) =>
                                            {
                                                Item = r;
                                                Item.PropertyChanged +=
                                                    (s, e) => NotifyOfPropertyChange(() => CanSave);
                                                if (onSuccess != null)
                                                    onSuccess();
                                            }, onFail));
}

And then the calling method becomes easier and cleaner, too:

public IEnumerable<IResult> OpenItemDetail(ToDoItem item)
{
    //CoroutineWrapper is a way of introducing a CoRoutine without
    // the called class having to implement IResult.
    IToDoItemViewModel editor = Items.FirstOrDefault(x => x.Item.ToDoItemID == item.ToDoItemID) ??
                                IoC.Get<IToDoItemViewModel>();
 
    Exception error = null;
    using (Busy.GetTicket())
    {
        yield return editor.GetToDoItem(item.ToDoItemID, null, e => error = e);
    }
 
    if (error != null)
        MessageBox.Show(error.Message, "System Error"MessageBoxButton.OK);
    else
        ActivateItem(editor);
}

 I also refactored the repository. Looks like you weren't aware of how to do a scalar query (query returning a single scalar value or object). Here's one of the methods:

public INotifyCompleted FindToDoItemByID(int ID, Action<ToDoItem> onSuccess = null,
                                            Action<Exception> onFail = null)
{
    EntityScalarQueryOperation<ToDoItem> op =
        Manager.ToDoItems.Where(c => c.ToDoItemID == ID).AsScalarAsync().FirstOrDefault();
    return op.OnComplete(onSuccess, onFail);
}

Previously, it returned all ToDoItems and then the ViewModel ignored all but the first one. That could be an expensive operation if you have a lot of ToDoItems. With the above approach, the DB only returns one record.

I think these were the biggest items. I did some minor refactoring in the ViewModel and made it so that it loads the ToDoList as soon as you click To Do, so you no longer need to click on the search icon. I haven't looked at the search yet. It doesn't seem to work. No matter what I type in the search field, I always get the full list.

I've put up a a full export of the latest framework with the CoProjectDF in the Samples folder on my SkyDrive. I'm not done yet with moving the other samples into the Samples folder, so I haven't added it to CodePlex yet.

https://skydrive.live.com/redir.aspx?cid=b37183c914f0fbe8&resid=B37183C914F0FBE8!162 

Coordinator
Aug 1, 2011 at 9:34 PM

John,
I've added CoProjectDF to the new Samples folder. I refactored the login and admin module. The previous code didn't take proper advantage of the AuthenticationService, hence there were some unnecessary workarounds. There was a coroutine missing, too. It did a logout followed immediatly by a login without using a coroutine. That probably was the source of whatever issue you ran into judging from your comments. I've also cleaned up some pattern violations. Some of the ViewModels had the EntityManagerProvider injected. That should be avoided. Only the repositories should use the EntityManagerProvider to get an EntityManager. In particular the AdminViewModel used the EMP to get the principal from the EntityManger. I changed that to inject the AuthenticationService. The only reliable way is to ask the AuthenticationService if the user is logged in and get the principal. The EntityManagers will eventually get the principal set, too, but not as early as you might expect.

I haven't refactored the LoginView yet. I haven't checked the original CoProject. Did all that code-behind come from the original project? That should be refactored properly into the LoginViewModel.

I've changed the sample data users to something more generic. Use CoProjectDF as the username and CoProjectDF1! as the password to login. I need to put a little ReadMe together and add it to the samples.

Take a look and maybe compare it to your version to see everything I changed and if you have any questions, let me know.

Marcel