Thursday, October 27, 2016

Kentico + MVC – Fix the split admin site

One of the options you have when using Kentico with MVC is to split the site into an administrative site and a public-facing site.
This is a nice separation of concerns so I would definitely reccommend this, if budget permits of course.
There’s a small snag with this though. By default a Kentico instance will show you the home page, but there is no content in an MVC site; it doesn’t have layouts and master pages defined in the CMS. Somehow that makes the site end up in an infinite redirection loop.

We’ve had to instruct editors to go to the /Admin url manually. This works but it’s an annoyance the customer doesn’t need.

The workaround
The workaround is to install the IIS URL Rewrite module on the server and add the following rule in web.config:

<system.webServer>
  ...
  <rewrite>
      <rules>
          <rule name="Redirect to admin login" stopProcessing="true">
             <match url="^$" />
             <action type="Redirect" redirectType="Permanent" url="/Admin/CMSAdministration.aspx" />
          </rule>
      </rules>
  </rewrite>
</system.webServer>
Now any request to the root of the site will get redirected to the admin home page.

Thursday, October 20, 2016

Kentico DataQuery API – Hydrating a datarow

When working with Kentico’s APIs you sometimes end up with a DataSet. A good example of this is the Search API. For use with transformations in the PortalEngine that’s usually not an issue. MVC however is very much geared towards dealing with strongly typed data. Fortunately you can easily go from a data row to a page or module class using the InfoDataSet class.

Under the hood
At the core of Kentico’s data access implementation is a key architectural descision: all data objects rely on a dictionary internally for the actual values of the properties.
So in the end, all the code you generate from Kentico for custom classes and page types is just a wrapper around that dictionary. You can see this when inspecting the code; the properties don’t have backing fields but instead use the GetValue / SetValue methods to interact with the dictionary.

The nice thing about this architecture is that it makes databinding really easy. There is no need to use reflection to dig up the PropertyInfo, you can call GetValue with the property name.

This is how databinding in XML transforms works. And it’s also the reason that you cannot bind POCO’s in XML transformations directly.

Hydrating datarows
The DataRows in a Table in a DataSet are in effect aldo dictionaries so, given the architecture of Kentico’s data objects, you can probably imagine how easy it is to go from a datarow to string typed Kentico content. To make it even easier there’s the InfoDataSet class. You create the class with a Kentico data object type as the parameter and it can then turn a DataRow into a typed object:

var set = new InfoDataSet();
var typedObject = set.GetNewObject(dataRow);

If you use InfoDataSet like this, it is ofcourse up to you to ensure that the data in the row matches with the data required by the class.

Friday, October 14, 2016

Kentico DataQuery API – Sub-selects

In lots of projects a requirement pops up to count the number of items in a sub set; the number of products in a category for example.

In SQL you’d probably solve this with a sub select or a Common Table Expression (CTE) for more complex scenario’s.

With the Kentico Data API you can do subselects as well.
It’s not well documented so it took me a while to figure it out but here’s how it works:

  CategoryInfoProvider.GetChildCategories(currentCategory.CategoryID, siteId: siteId)
   .Columns("CategoryDisplayName", "CategoryID")
   // "(SELECT COUNT(*) FROM CMS_Category c2 WHERE c2.CategoryParentID=CategoryID)"
   .AddColumn(
      new DataQuery().Source(s => s.SourceExpression = "CMS_Category c2")
      .Columns("Count(*)")
      .Where("CMS_Category.CategoryID = c2.CategoryParentID")
      .AsColumn("ChildCount"))
   .Result;

This particular query will get a DataSet with the category names, ids and the number of child categories. Unfortunately, you do need to use a DataSet here because using a typed result set will not give access to the ChildCount column.

Thursday, October 13, 2016

Kentico DataQuery API

In recent projects we’ve been making heavy use of the Kentico DataQuery API. This API was introduced in Kentico 8 to replace the provider-based data access methods.
It’s sort of like Linq but not quite the same, though you can mix it with Linq to some degree.

In upcoming posts I’ll dive into some of the gritty details and share some of the lessons learned while applying the Kentico DataQuery API in real life projects, both with the classic Portal engine and MVC.

Why should you use this API?

Mostly because Repeaters will only get you so far. As soon things get more complicated you’ll need to fallback to a data access method that gives you more control.
You can write very complex queries in 10 or 20 lines of code with this APU. It’s very much tuned to Kentico and it’s content.

One of the huge benefits of this is that the queries you build in code are actually testable. Yes, you can write integration tests to exercise your code automatically. And yes that actually works.

What are the drawbacks?

No caching. That’s a big one.
All that lovely caching that you get for free with most of the Kentico Portal Engine controls is now your own concern. You do still get to use Kentico’s caching with the handy cache dependencies that we all love to manage on our data intensive web parts. But now you have to write a bit of code to make that work. More on that in another post.

Posts in this series

Further reading:
Introduction to DataQuery
Kentico 8 Technology – DataQuery API