Update
So I got the csinc site switched over to using v3 api instead of the v2 CloudDB strongly typed service. Generally, I like it because it allows greater flexibility. That could have been true for v2 api, but I haven’t tried it so I can’t say. The CloudDB hasn’t put together the docs for this yet, so I’ll show you some code to use it below.
Why use it
First, it keeps the website portable. It doesn’t matter where it’s hosted because the datastore doesn’t change. Second, We can tweak content and even some behavior/layout stuff easily by making the change using the clouddb website.
Implementation
I’m not entirely settled with our implementation so far. How we read columns and set object properties needs work. Also, I re-factored the base to pass in a context object basically just to pass around a pointer to the IWindsorContainer instance so it would work in the web app and in the test project. It’s one of those quick hacks which you’re not quite happy with but don’t really have another good idea at the time. I just wanted my tests to pass.
Getting started
First you have to get an invite, and then set up a clouddb account. Once done, add the clouddb api url as a webreference and begin coding. Start with the login code:
1: public static Token Login(string user, string password)
2: {
3: using (CloudDB cdb = new CloudDB())
4: {
5: return Login(cdb, user, password);
6: }
7: }
8:
9: public static Token Login(CloudDB cdb, string user, string password)
10: {
11: Token tok = cdb.LogIn(user, password).Result;
12: return tok;
13: }
Using an instance of CloudDB and the Token, you call whatever api method you need. Our site only uses reads so far. So here’s how we get a list of rows:
1: public static RowsResponseData GetRowData(CloudDB cdb, Token token, string appName, string entityName, Predicate[] predicates)
2: {
3: App app = cdb.GetApplicationByName(token, token.UserID, appName, false, false).Result;
4: Entity e = cdb.GetEntityByName(token, app, entityName, false).Result;
5: RowsResponseData rowData = cdb.SearchEntity(token, app, e, predicates, 0, 0, 0, 0).Results;
6: return rowData;
7: }
In the above code, the Predicate array is used to specify which rows to get back from clouddb. That’s how we get a single match if we want. Just query for the id or other unique criteria. Here’s how we handle that in our record base class:
1: public static T GetRecord(IAppContext context, string cacheKey, string entityName, Predicate[] predicates)
2: {
3: CachedItem ci = DataCache.GetItem(cacheKey);
4: if (ci != null) return (T)ci.Data;
5:
6: try
7: {
8: ICloudConnectionSettings connectionSettings = context.Container.Resolve<ICloudConnectionSettings>();
9: RowsResponseData rowData = CloudDBDataAccess.GetRowData(connectionSettings.CloudDBApplicationName, entityName, connectionSettings.CloudDBUser, connectionSettings.CloudDBPassword, predicates);
10: T item = new T();
11: item.Init(rowData.Data, 0);
12: DataCache.Add(cacheKey, item);
13: return item;
14: }
15: catch (Exception er)
16: {
17: T item = default(T);
18: DataCache.Add(cacheKey, item);
19: return item;
20: }
21: }
You’ll notice that caching is also handled at that layer so the specific model doesn’t have to know or think about it. (Yes, there are things I can do to improve this. Remember, time for our own site isn’t a high priority versus time for clients.)
..and a sample usage:
1: protected bool ShowDynamicContent()
2: {
3: return ShowDynamicContent(Request.FilePath.ToLower());
4: }
5:
6: protected bool ShowDynamicContent(string contentName)
7: {
8: var pageContent = PageContent.GetByPath(new AppContext(), contentName);
9: if (pageContent != null && pageContent.IsPublished)
10: {
11: PropertyBag["contentTitle"] = pageContent.Title;
12: PropertyBag["contentDescription"] = pageContent.Description;
13: PropertyBag["content"] = pageContent.Content;
14: RenderView("../shared/contentview");
15: return true;
16: }
17: return false;
18: }
1: public void Index()
2: {
3: //show dynamic content if available, defaults to view file content if not
4: ShowDynamicContent();
5: }
Good to know
Clouddb data is described with Entity objects representing the table, Column objects describing the columns for data, and Row objects containing the data. Think of it a little like a DataSet in .Net. You’ll need to know a little about the columns in the data, and then read the values from the Rows array. Also, you’'ll need to know the application name, which is the specific clouddb database in your account.
That’s a simple overview. Hopefully it helps. There is more to it, but that should get you started.
