Wednesday, August 3, 2011

Introducing MVVM and customizing the UI by role

First we will add a View-Model layer behind the home page, and customize the UI based on the role of the logged in user.

Authentication data is provided by several ASP.NET tables.

The Web.config file in the project contains various configuration parameters, two if which are:
  • roleManager
  • authentication
Added details for membership, roles, and authentication to Web.config file. Had to change all names which referred to SLEventManager, to Eveneter. Not sure if this was really needed.

Adding a property for the dbName and connection string to Web.config

Done adding everything. Now when I run the application, I get an error message:

--------------------------------------------------------------
Error 1 The "CreateRiaClientFilesTask" task failed unexpectedly.
System.Web.HttpException (0x80004005): Sections must only appear once per config file. See the help topic for exceptions. (C:\Documents and Settings\pshah\my documents\visual studio 2010\Projects\Eventer\Eventer.Web\web.config line 53) ---> System.Configuration.ConfigurationErrorsException: Sections must only appear once per config file. See the help topic for exceptions. (C:\Documents and Settings\pshah\my documents\visual studio 2010\Projects\Eventer\Eventer.Web\web.config line 53)
at System.Web.HttpRuntime.HostingInit(HostingEnvironmentFlags hostingFlags, PolicyLevel policyLevel, Exception appDomainCreationException)
at System.Web.Compilation.ClientBuildManager.EnsureHostCreated()
at System.Web.Compilation.ClientBuildManager.CreateObject(Type type, Boolean failIfExists)
at Microsoft.ServiceModel.DomainServices.Tools.CreateRiaClientFilesTask.CreateSharedTypeService(ClientBuildManager clientBuildManager, IEnumerable`1 serverAssemblies, ILogger logger)
at Microsoft.ServiceModel.DomainServices.Tools.CreateRiaClientFilesTask.GenerateClientProxies()
at Microsoft.ServiceModel.DomainServices.Tools.CreateRiaClientFilesTask.ExecuteInternal()
at Microsoft.ServiceModel.DomainServices.Tools.RiaClientFilesTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask, Boolean& taskResult) Eventer

--------------------------------------------------------------

This does not make any sense. The said configuration element is not even present in my file, and there is definitely nothing like this at line 53.

Going to try doing a Google search. Looks like this problem was happening because the 'profile' element was specified multiple times. Nothing in the error message said that. Bad ... very bad.

Fixed that error and running the test. I am able to load the login form, but cannot login with credentials specified in the tutorial. Since I do not get a connection error, I am assuming that there is no problem with the database connection. Perhaps the data does not exist? I opened the data table from the database configuration view, but that shows me the schema, and not the data.

Since I cannot login with the provided credentials, I will register a new user. I was able to do that successfully, and could also login with that user. I will use this account for the time being.

Create the Register For Event Functionality:
I added the StackPanel (containing the Register for Event functionality) after the current StackPanel as suggested in the tutorial. But I get some compilation errors. Instead of using that code, I added a StackPanel, within which I added GridPanel, and within that I added two buttons - one for registration and one for deregistration.

The tutorial says, that now we need to add a new class for the View Model, called ViewModelBase. However, it does not say which folder this class should be put in. Also the suggested shortcut SHIFT-ALT-C, does not add a new class in VisualStudio2010, with Silverlight 4.0.

We need to create the base class ViewModelBase, because when an attribute changes in the ViewModel, the UI will have to be updated, This is usually done by implementing INotifyPropertyChanged. We provide a default implementation for this interface in the ViewModel base class.

I created ViewModelBase and also put the code specified in the tutorial in that class. However, I totally o not understand the code. A lot of questions come to mind, perhaps some of them will be answered as I move ahead in the tutorial.

Next I created the ViewModel folder which will contain specific ViewModel classes. Specific ViewModel classes are created in correspondence to specific view XAML files. I am not sure why we did not create ViewModelBase in the ViewModel folder.

Created a class called HomeViewModel.cs in ViewModels folder,a nd made it extend ViewModelBase.cs

THERE ARE WAY TOO MANY THINGS THAT DO NOT WORK AS EXPECTED IN THIS COURSE, WHICH IS A FIT INFURIATING FOR A BEGINNER. I AM GOING TO CREATE ANOTHER COURSE WHICH WILL HOPEFULLY HAVE MORE THINGS WORKING AS THEY SHOULD.





Introducing the View Model

So far we have used data forms provided by WCF RIA services to talk to the data. This is fine for small applications or for certain data objects, but once the application grows, the state we want to show the user may not be in 1 - 1 correspondence with the database tables.

We also do not want to show all the data views to all users, we would like to control the access of what a user does in the system.

Putting all our data access code in the XAML code behind, is not good from the perspective of testability.

For all the above reasons, we usually add a layer between the View (XAML and it's code behind), and the model (domain service classes), to perform all the the above tasks. This layer is the View-Model layer.

Monday, July 25, 2011

Creating a track and session hierarchy

In this exercise, we want the user to be able to view/edit tracks for the events. Since each event can have multiple tracks, this exercise will show us how to deal with master-detail relationships.

First, the tutorial says that our default applications, DomainService only returns a list of Events and not the Entities which are related to the Event. We could get it to do a lazy fetch, but they suggest that we replicate the GetEvents() method and refactor it so that it returns the Tracks and Talks also.

I created a new method in EventManagerDomainServices.cs, which will return the Tracks and Talks for the events. This method is for the EntityFramework. BY adding this method we are enhancing the Entity Framework's functionality.

public IQueryable GetEventsWithTracksAndTalks()
this.ObjectContext.Events.Include("EventTracks.Talks");
}

We will make our Event DataGrid bind to this Query.

&<riaControls:DomainDataSource
    AutoLoad="True"
 &;nbsp;  d:DesignData="{d:DesignInstance my:Event, CreateList=true}"
    Height="0"
    LoadedData="eventDomainDataSource_LoadedData"
    name="eventDomainDataSource"
    QueryName="GetEventsWithTracksAndTalks"
    Width="0" Margin="0,0,320,480">
  <riaControls:DomainDataSource.DomainContext>
    <my1:EventManagerDomainContext />
  </riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>

However, this is not enough. We have enhanced the Entity Framework, but we also need to tell RIA services to include this data. By default RIA services is very restrictive, and will not include the data.

[Include]
EntityCollection EventTracks { get; set; }


Adding the include annotation to the EventTracks property will ensure that the data comes from RIA Services.

Now we need to select Event.EventTracks from data sources, and drop it on the view next to the Event details grid. In Silverlight when we select a dependant property, it will automatically be bound to the selected master record.

What this means is that we will only see related Event Tracks, depending on the Event which is selected.

Creating New Events in the Application

In this exercise, we will add the functionality to create new events in the application. I think we should be able to reuse a good amount of code we wrote to edit events.

First, we will add another button to the main page (Home.xaml) for creating new events.

I opened Home.xaml, selected a button from the Toolbox, and dropped it into the view for Home.xaml. Next, I repositioned the button, and changed a few properties, such as the text, name, etc.

Next, I created the click handler, in which I added code to create an event with some placeholders, and then navigate to the edit page to edit it with actual data. I do not like this way of doing things. What if the user does not put in actual data immediately. Then we will have an application with a bunch of phantom events. Why can we not straight away ask the user for details, and then save the event only when the use creates the details.

Anyways, got the application working till now. I am able to create new events. However, from a usability perspective, when we save an event, at the moment we do not get any notification. At least we should take the user back to the HomePage so they can view the updated list. Implemented this feature by invoking NavigationService.Navigate in the click handler of the 'Save' button.

The lab page for the assignment explains why we create a new domain context object instead of re-using the one we already have (similar to the the domainDataSource object we used in editEvent... though I do not know what scope this object is available in, and how/(if at all) it is shared among the views).


Silverlight Assembly related problems keep on recurring

I am again getting the assembly related errors. Specifically it seems that it cannot generate the client side code for the Silverlight application. The error I am getting is:

CreateRiaClientFilesTask task failed unexpectedly. The reason is that it could not load some file from the assembly. Or at least that is what I think it is, because I get a FileNotFoundException somewhere in the call stack. I am not quite sure what an assembly is. Is it a file, or a dll, or a bunch of files? A bit of reading also seems to suggest that the real problem could be something else, which is not being reported correctly.

Anyways, I think the first thing I should do is turn on FusionLogging (here's how), which logs assembly related errors.

I opened the VisualStudio SDK CMD prompt, and types fslogvw.exe, which opened up the 'Assembly Binding log viewer'. However, the log viewer does not show me any error messages, whereas VS2010 does have the same errors. Someone on StackOverflow mentioned that it might help if we setup a custom path for logging. Great... I s now have a custom path for logging. Setting a custom log location got it to work. Gosh this is really crazy. I had no idea Microsoft products were so buggy.

Now, very interestingly, once I had the logging working, and I rebuild the application (for the nth time today), it just started working. I seriously do not know what to make out of all this. I am trying hard not to curse :-)

I guess I will leave this issue as it is for now, and revisit it when it crops up again.

Wednesday, July 20, 2011

Editing Entities

I am now watching the 2nd video in module 2, which describes how to edit Entities. Completed watching the video, but I will not post the timeline or notes right now. I want to do the lab, and then re-watch the video (will post the timeline then).

Moving on to the lab:
First we need to create an EditEvent page. Created the EditEvent.xaml page using the Silverlight Page template. This template also created EditEvent.xaml.cs, a C# file (which I suppose is the client code referred to in the video).

Next, I opened the Data Source window, selected Event (selected 'Details' from the drop down in front of 'Event'), and dragged the control onto the EditEvent page.

Next, I created an 'Edit' button, which we will click to edit the selected Event. The Button got created in the center of the screen under the datagrid control. I am unable to move it by dragging and dropping... I know there has to be a way to do this. Plan 2 is to try to re-position it by specifying location parameters for the button in the XAML file. I think I am unable to move the button because it is in a StackPanel. If it were in a Grid, then I would have been able to move it. However, the DataGrid control (IIRC) needs to be in a Panel container, so we may have to add a Grid to the Stack Panel and then add the Button inside the Grid.

I then added a click handler to the button, so we can Navigate to the EditEvent page. This page is given a query string which has EventID=id, where id is the id of the selected Event.

The application runs, but I realized that whichever button I click, the EditEvent page shows the same event for editing. This is because the EditEvent page still does not do anything with the EventID we passed it. We need to implement the method 'OnNavigatedTo'. In this method we will get the EventID from the url and then create a filter which will determine which record to show.

// Executes when the user navigates to this page.


protected override void OnNavigatedTo(NavigationEventArgs e)
{
string eventId = NavigationContext.QueryString["EventID"];
eventDomainDataSource.FilterDescriptors.Add(
new FilterDescriptor
{
PropertyPath = "EventID",
Operator = FilterOperator.IsEqualTo,
Value = eventId
});
}



I got the edit screens, and then added a Save button. The Save button's event handler calls submitChanges on the DomainDataService



eventDomainDataSource.SubmitChanges();



This is very interesting. I read that the client part of the domain data service, keeps track of which properties on all the Entities have changed. When we call the above method, it will save all changed Entities. So RIA services manages all the batching. I guess this batch might be run in a transaction, or perhaps we can configure it to run either way...


Got the basic infrastructure in place. I am able to select an Event, click on the Edit button, and the Edit Event page shows up. However, when I edit the Event details, and click on 'Save' the Event does not get saved.

I put a breakpoint in the Event handler code to find out what is happening, and it seems that an Exception is being thrown. (sidenote: Since the compiler did not force me to catch the exception, C# either does not have checked exceptions, or this particular Exception is a runtime Exception). This happened because I had not checked the 'enable editing' checkbox while creating the ADO Data Model. This problem can be resolved by creating placeholder methods in the domain service class for basic CRUD operations.

However, since I wanted to practice doing the project again, I deleted the project and recreated it, this time being careful to select the 'enable editing' checkbox.

Everything is working fine, however I keep running into the 'code generation' errors. Not quite sure why...


Tuesday, July 19, 2011

Add data bindings and domain context

Opened the 'data sources' view, and selected 'Event', and dragged it into the main view area of Home.xaml .

I opened the data sources view, selected 'Event' and dragged it into the main area of Home.xaml . Then I resized the control to make it larger, and tried to test it by right clicking the project from the solution view, and selecting 'view in web browser'.

This did bring up the browser, and started initializing the Silverlight plugin, but stalled at 100%. Then I tried doing a CTRL-F5 on the project, and that worked just fine.

I am not sure why the former option did not work. Asked on the course forum.

Now I am able to view event data in the browser from the application.

Creating domain services

Now that we have the Silverlight application, the database, and the Entity Data Model, we will now create the Domain Service class for the Entitites. I am not totally sure what the Domain Service will do, but I think it provides classes and API's which the application can call from the client side Silverlight control.

I right clicked on the 'Services' tree node, and selected, 'Add new'. Then I selected the 'Domain Service' class template, gave it a name, and selected the Entities we want to expose in the Domain Service.

Some noteworthy points and questions:
  1. What exactly is a domain service class?
  2. The domain service class extends the class 'LinqToEntitiesDomainService'
  3. The domain service class has the [EnableClientAccess()] annotation. Is this really an annotation, or is it something else. The () seem to suggest that it is invoking some method, so this might be a special syntax to specify that some internal method needs to be invoked at some time. Is this at build time, runtime ? Not quite sure.
  4. The entire namespace is enclosed in {}
  5. A file called EventManagerDomainService.metadata.cs was also created. This file has a bunch of partial classes. Need to find out what partial classes are.

Monday, July 18, 2011

Database woes

Now that the project is created, I need to connect it with a database. The tutorial template comes with an mdb file, which I can use to create the database.

I selected app->data and tried to create a database by selecting the mdb file which came with the tutorial. However, I was not able to create the database. I got an error message which said that SQL Server 2005 Express or 2008 Express should be installed. I thought that VisualStudio 2010 came with SQL Server 2008 Express... oh well...

I downloaded SQLServer 2008 Express with Tools and
tried to install it. The installation exited with an error message because .NET 3.5 SP2 was not installed. I think I must have uninstalled it when I removed all instances of SQL Server from my system.

Installing .NET 4.0 now... installed.
Ran the SQL Server installer again, but I get the same error. Looks like it either works only with .NET 3.5 or maybe .NET 4.0 does not have something which .NET 3.5 has. A Google search revealed this post, which suggests that the .NET 4.0 client profile may not be good enough... we might need to install the whole deal (whatever that is...)

I am a bit irritated with this whole dependen
cy nonsense... MS you really need to get your act together.

I am now installing .NET 3.5 with SP1. I hope it does not conflict with the .NET 4.0 I already have installed on my system. Hopefully, I will be able to install SQL Server after .NET 3.5 .

Now, I have .NET 2.0, 3.5 SP1, and 4.0 all installed on my machine. SQL Server dost thou needest anything more ?

Running SQL Server 2008 express installer again. This time I ran into an application error related to landingpage.exe which is described very well on this page. As suggested, I deleted the Microsoft_Corporation folder.

This time the installation failed because Windows Power Shell was not installed, and apparently it is a pre-requisite for SQL Server 2008 Express. Oh well and on we go... trying to get Windows Power Shell.

Installed Windows Power Shell 1.0 ... re-running the SQLServer rules

At some point in the installation (server configuration) I got an error message which said that the credentials I have provided are not valid. I have not provided any credentials. Some Googling suggested that there is a drop down list in the username section. We should select any item and make sure there is no password. Did that and it worked. Account names are as follows:

SQL Server Database Engine : NT AUTHORITY\SYSTEM
SQL Server Browser NT AUTHORITY\LOCAL SERVICE

Selecting mixed mode for authentication (SQL Server Authentication and Windows Authentication)

Finally SQL Server is installed. I CANNOT BELIEVE THIS!

Next, I went back to the project, right clicked on 'App_Data', and selected the mdf file for this lab from the downloaded tutorial labs. It seemed to have accepted the mdf and looks like things are moving ahead.

Just to verify, I double clicked on the database, which opened the database viewer. The database shows several Event Application related tables, as shown in the image below.



Create The Entity Data Model:
Since we want to be able to access the server side Entities in the Silverlight client, we need to create the Entity Data Model. I right clicked on the Eventer2.Web node in the Solution Explorer. Then I selected C#->Data and selected 'ADO.NET Entity Data Model'. I set the name to 'EventManagerDBModel', and then in a later wizard screen, specified that the model needs to be created from an existing database (SEventManager.mdf). Clicking on Finish, finally showed me the data model for the application.

Next, I rebuild the project, because without that the EDM we just created would not be available to RIA services link.


Thursday, July 14, 2011

Creating the first project

I watched the first video in module 2, which discussed RIA Services and Data Binding.

Here is the timeline (as relevant to me)

[00:00] Introduction
[01:13] The WCF RIA Services link (what will this do?)
[03:24] RIA Domain Service
[06:11] Data Binding
[06:45] Creating New Project
[08:46] The login and registration pages
[09:18] Adding data to the application (along with the Entity Data Model and Domain Service)
[12:40] Adding a data grid
[13:57] Launch the application in the browser

My Notes:

We do not need to write DTO by hand, no dealing with concurrency, RIA also does pagination and change tracking

DomainServices provides methods which can be accessed on the client. It usually consists of methods which will provide us with basic CRUD services (auto generated which can be refactored by us)... The Entity class can be implemented by one of many technologies... the client gets the domain context through which it can call methods of the domain service.

RIA Services also give us automated data binding

The client.bin folder contains the build output which is the xap file.

We do not necassarily have to use the Entity framework

RIA services provides observable collections which will observe the data in the actual database tables

RIA services automates a lot of things which we would have to otherwise write by hand


Creating the project: working on Activity 1

The first thing I need to do is create a new Silverlight Business Applications Project. I opened Visual Studio 2010, and selected "new project", then selected "Visual C#". On the right hand side, I should have seen an option to create a Silverlight Business Application, but I see only an option to create a Silverlight Application. Perhaps, I need to install Silverlight Tools for Visual Studio 2010.

I downloaded Silverlight 4.0 tools for Visual Studio 2010. With Silverlight 4.0 tools, I can create a Silverlight Business Application.

Monday, June 27, 2011

Creating a Silverlight application

To create a Silverlight application in Visual Studio, all we have to do is to go to File->New Project and select "Silverlight application".

All the details including the name of the project, it's location in the filesystem, etc can be configured by changing values at the bottom of the window.

When we create an application, the wizard will prompt us to find out if we want to create just a Silverlight application (I am presuming for the desktop), or we want to create an ASP.NET application which is a web application bundled with the Silverlight app. If we choose the latter, we will have two applications. One the Silverlight app, and the web app. The web app will run on the browser, and will pull the Silverlight app for running in the Silverlight plugin in the browser.

Since Silverlight has a plugin, it seems very similar to a Java Applet, but I am sure they have taken more care to allow it to interact with Javascript, etc on the webpage.

Starting to learn Silverlight

Today I started looking for some tutorials to learn Silverlight. Silverlight.net has a good many video as well as text tutorials. However, most of these tutorials do not mention the order in which we should view / read the tutorials.

If you are beginning to learn Silverlight, you will find the Silverlight Essential Playlist of videos to be very useful. Unfortunately these videos are not listed in the order in which they should be viewed. Fortunately, since these videos are part of a free tutorial from Lynda, you can see their order on Lynda.com here.


Silverlight is a Rich UI technology which in ways is similar to Java Applets, Adobe Air, Flash, and the more recent HTML5. Silverlight initially began as a plugin, but from what I understand now, it is a full fledged business application platform, with technologies such as RIA web services, etc.

I found the UI to be very slick, and as expected Microsoft has created a very user friendly environment called Expression Blend to design the UI for Silverlight applications. The UI is represented as XAML files, which is a declarative language for user interfaces in Silverlight.

Another nice thing I noticed in Silverlight is that, the links within the plugin are exposed in the browsers navigation bar. This makes them bookmarkable.

Silverlight is available on all popular platforms - Windows, Linux, Mac. On Linux it is available as the Moonlight plugin.