Initial Thoughts on RIA Services
At Mix 09, Microsoft unveiled RIA Services. Subsequent blog entries from Nikhil Kothari and Brad Abrams provide good introductions. In a nutshell, RIA Services is a framework for making it easy to build a middle-tier for RIA applications, such as Silverlight. RIA Services makes it easy to communicate with the server and provides other essential services, such as validation and asynchronous processing. Not that you can’t do this today with Web Services, but RIA Services does a lot of this work for you. In my case, it also lets me code business logic the way I’m accustomed, with business objects, yet does all of the plumbing work that I really don’t want to do. If you’re interested, download the bits and check them out. Remember, this is Early Beta and you should install it on either a virtual machine or a computer designated just for test software.
Brad Abrams on LINQ Support
var customerArrayList = new ArrayList();
public
interface ICustCollection{
Customer GetAt(int index);
int GetCount();
}
Notice that the interface doesn’t have standard .NET IEnumerable members like MoveNext and Count. Here’s an implementation of that interface:
{
// customer collection stuffpublic Customer GetAt(int index)
{
// whatever internal implementation they have
// – could possibly be from a COM interop scenario
return new Customer();
}
public int GetCount()
{
return 1;
}
}
// add some stuff to cust Coll
for (int i = 0; i < custColl.GetCount(); i++)
{
// do something with custColl,
// assuming it has members
}
If you’re accustomed to being able to use foreach or (better) LINQ, the code above is probably pretty ugly and cumbersome, especially when you have some serious filtering or collection manipulation to do. So, I decided that I wanted these collection classes to be IEnumerable<T> and solved the problem with Extension Methods. Here’s how I added an extension method to ICustCollection, so that I could translate the results into List<T>, which is IEnumerable<T>:
{
public static List<Customer> ToList(this ICustCollection custs){
var custList = new List<Customer>();
// build a List<CustomCustCollection> from custs
for (int i=0; i < custs.GetCount(); i++)
{
custList.Add(custs.GetAt(i));
}
return custList;
}
}
Notice that both the class, ThirdPartyApiCollectionExtension, and the method, ToList, are static. Also, notice that the first parameter (only parameter in this case) is ICustCollection, modified with the this keyword to specify that ToList extends ICustCollection. The implementation of ToList simply extracts everything from custs and returns it as a List<Customer>. Now, I can use LINQ on the data like this:
List<Customer> custList = custColl2.ToList();
var newCustomers =
from cust in custList
where cust.Name == "Jack"
select cust;
Notice how the preceding code calls ToList on custColl2. That’s because custColl2 is ICustCollection and ToList is an extension method that operates on ICustCollection, as described for the ThirdPartyApiCollectionExtension class above.
A New Look for Visual Studio 2010
MyCloudTime is Launched!
Rocky Mountain Tech Tri-Fecta
Local Database Cache and |DataDirectory|
Every once in a while it’s easy to get sidetracked by something that is totally irrelevant to what you are trying to accomplish. Case in point is the Local Database Cache, where the wizard generates a *.sdf (compact framework database) at the top level of your solution. When you start working with your code, its easy to look at the *.sdf at the top level of your solution and say “That’s where my database is”. One might even be tempted to add a reference to the database (located at the top level of the solution) through Server Explorer, making it easier to observe changes while configuring synchronization and testing an occasionally connected client.
The problem occurs when writing code to execute synchronization and testing to verify that all is set up properly. When verifying, its easy to open the *.sdf through Server Explorer to verify that synchronization was successful, but the changes aren’t there. This sets off a sequence of debugging code to verify that changes are being made and there aren’t any errors or exceptions. When the code looks and runs perfect, one would verify that the database being looked at at is the same one in the solution. Perhaps a few random queries on search engines would be appropriate too, yielding nothing. After having checked the connection strings, which were autogenerated, it might become apparent that the location of the database isn’t necessarily the same as what the connection string indicates, especially since the Data Source contains the |DataDirectory| macro.
As it turns out, there is an *.sdf file in appDir/bin/Debug. Considering the |DataDirectory| in the connection string, the following blog post that explained this situation quite well:
http://blogs.msdn.com/smartclientdata/archive/2005/08/26/456886.aspx
By default, |DataDirectory| means that the local database cache will be created in the same location as the *.exe, which is where all of the updates occur. Therefore, setting Server explorer to look at appDir/bin/Debug/*.sdf does the trick. Of course, changing the project configuration from Debug to Release would mean that the database would be in appDir/bin/Release/*.sdf. The post describes ways to alter this location, but the default behavior seems fine for most scenarios; especially attractive is the smart client scenario where you really don’t know the physical location of the *.sdf until runtime.
Going back to the original distraction motivating this blog post, it might be best to delete the *.sdf created by the Local Database Cache wizard; Otherwise, someone might accidentally think the *.sdf at the top level of the solution is the client database cache and waste their own time in a manner described in this post. 😉
Membership.GetUser Returns null in the Login Control’s LoggedIn Event
Ran into a glitch where I couldn’t retrieve the MembershipUser during the LoggedIn event. I wanted to cache some info in Session that I would be using on multiple pages. Yeah, I know about the tradeoffs of keeping info in Session state, but I wanted to it anyway. 😉 Normally, passing the user name should work, like this:
MembershipUser user = Membership.GetUser(LoginCtrl.UserName);
Problem was that the UserName property of LoginCtrl (the Login control reference) was blank, resulting in a null return value. This is weird because the UserName is normally available during this event. As it happens, User.Identity.Name was blank also; Too strange.
After Live Searching (hmm, lacks the ring of Googling) the following blog entry revealed the culprit:
http://www.codeplex.com/cssfriendly/WorkItem/View.aspx?WorkItemId=7187
To summarize, the link describes a bug in the CSS Friendly Control Adapters where the UserName and Password aren’t set if you switch the Login control to use templates. So, here’s the fix:
string userName = (LoginCtrl.FindControl(“UserName”) as TextBox).Text;
MembershipUser user = Membership.GetUser(userName);
Needless to say, a CodePlex issue got my vote. 🙂