Kentico 12 MVC Design Patterns - MVC Widget Tips

   —   

Learn some tips and best practices when developing and integrating MVC Widgets into your Kentico 12 MVC site.

Warming Up To MVC Widgets

In my previous post here on DevNet, Kentico 12 MVC Design Patterns - A Primer, I covered several tips to help developers lay a solid foundation for their Kentico 12 MVC projects.

In this post I'm going to cover the new and powerful ๐Ÿ’ช UI technology that comes with Kentico 12 MVC applications - MVC Widgets.

Before we begin, I'd recommend you familiarize yourselves with the MVC Widget technology, by either watching the video below or reading up on Widgets in Kentico's documentation.

Now, let's dig in!

Widgets Can Be Project Specific

There's been a fair amount of talk of teams building up general purpose, reusable libraries of Kentico MVC Widgets to help improve development efficiencies on projects ๐Ÿค“.

Also, if we look at the Widget selection of what is in the Kentico Marketplace, we are going to see a lot of very generic reusable Widgets ๐Ÿ˜‰.

This is primarily because the only types of Widgets that would get a lot of use in the broader Kentico community are going to be those non-business, non-project specific Widgets that any developer can grab and integrate into their application.

I think, though, that this focus detracts from an awesome (and maybe more common?) use-case for Widgets - flexible outlets of content that are very client and site specific ๐Ÿค”.

[As an aside, I'd love to see more general purpose Widgets in the Kentico Marketplace and I don't want to discourage any developers from sharing that next cool Widget!]

We shouldn't be afraid to build one-off Widgets for our Kentico 12 MVC sites. Widgets don't have to be infinitely flexible and re-usable to be useful.

We should feel OK to go build that "Featured Ceramic Cactus Plant Pottery Image Carousel Widget" if it's helpful to display that content in many places around our sites ๐Ÿ˜Š.

Widgets Simplify Models, Views, and Controllers

In MVC development, we typically have 3 required architectural pieces - Models, Views, and Controllers.

[However, we might end up with many more, as noted in my post Kentico 12: Design Patterns Part 20 - Choosing a Solution Architecture.]

As pages in our applications grow in complexity, in terms of the content they display, our Models, Views, and Controllers increase in complexity.

There are ways to simplify them with things like Partials and Child Actions.

We can also think of Widgets as Child Actions * 100 ๐Ÿ˜ฒ!

They remove portions of content from our normal MVC code for a specific page. If we use the same content on multiple pages, we can build the Model, View, and Controller for a Widget once, and reuse that functionality ๐Ÿ’ช.

[Another option to simplify the MVC pieces is to render content client-side using JavaScript and a Web API Controller, which I cover in my post Kentico 12: Design Patterns Part 16 - Integrating Vue.js with MVC.]

Widgets vs Structured Content

Widgets in Kentico 12 MVC are a very powerful tool ๐Ÿ”ง both for developers (eg: they can simplify MVC patterns) and content editors (eg: the rich layout building and editing capabilities).

As Kentico developers building new sites in the MVC world, we need to know when it's best to leverage Widgets as a technology solution and when to rely on existing options.

It's really important to note something about Widgets:

They are meant to improve the flexibility of the presentation of content, not the management of content.

What does this mean exactly?

Content editors using Kentico EMS have the responsibility of keeping content updated and consistent, and in larger sites or organizations content governance might be a key part of their job.

Inline Editors, while enabling a slick content authoring experience, typically don't lead to the most manageable content.

If content is stored in a Document's Page Type custom fields, that content can be aggregated or selected for specific reuse elsewhere on a site.

It's also manageable in a distinct location with the robust system of Kentico EMS's Form Controls validation and type restrictions.

Content that is stored exclusively in a Widget (eg: when entered through an Inline Editor that stores the text in the Widget itself or a Form Component) cannot take advantage of anything mentioned above out of the box ๐Ÿ˜‘:

  • โŒ Content aggregation or reuse
  • โŒ EMS Form Control validation
  • โŒ Custom Page Type field type restrictions

This means that in typical Widget development, our best option is to source content from Documents in the content tree, whether those are Pages that we can navigate to, or structured content without associated presentation.

This recommendation leads to the following pattern:

  • โœ” Create custom Page Types
  • โœ” Add Documents using these Page Types to the content tree and manage content there
  • โœ” Expose content through customizable Widgets

With this approach, as opposed to adding and managing content in the Widget itself, we get all the benefits of content maintainability and presentation flexibility ๐Ÿค—.

Please note:

Skipping robust content modeling using custom Page Types in exchange for doing everything through Widgets should be considered an ๐Ÿงจ Anti-Pattern ๐Ÿ’ฃ in Kentico 12 MVC development.

Don't Forget Caching

Since content editors can use Widgets to dynamically alter the content of any pages implementing Page Builder functionality, the data sources supplying data to Widgets could be called on many, many times throughout a site.

Imagine a "Featured Products" Widget, which lists a series of SKUs in a particular public status, is used on 20 different pages to drive traffic to these products.

Even with Output Caching enabled, loading those 20 pages in succession would result in the product data being queried from the database 20 times ๐Ÿ˜ฑ.

Widgets are an easy place to implement data caching ๐Ÿง!

If we properly implement data caching for a Widget, no matter how many landing pages content editors create that use our "Featured Products" Widget, the data will only be queried from the database when the first landing page is visited - all successive pages will pull the data from the cache.

[To learn more about caching database queries in Kentico, check out my post Kentico 12: Design Patterns Part 12 - Database Query Caching Patterns.]

Leverage Widget Scoping

Not all Widgets belong on all pages. Some Widgets might be specific to a certain part of the site, or should only be used with specific page types.

Kentico enables developers to place restrictions on the type of Widgets that content editors can place on a page.

There are a couple different patterns for defining these restrictions ๐Ÿค”.

Editable Area Definitions

One option is to hard code the list of allowed Widgets directly in the call to HtmlHelper.EditableArea() which defines where on the page Kentico should enable Page Builder functionality.

This simple approach would look as follows:

<div class="section"> @Html.EditableArea( // The Editable Area name "my-area-name", // The default Widget Section identifier "myDefaultSection", // The allowed Widget identifiers "widgetOne", "widgetTwo", "widgetThree") </div>

This approach is fine for getting started but will quickly start to cause problems ๐Ÿ˜’.

Even if we replace the "Scattered Strings" (eg "widgetOne") with references to constant identifiers, we are not being clear as to why those Widgets are allowed here.

And, if we add a new multi-purpose Widget, it won't show up until we update every Editable Area definition ๐Ÿ˜–.

A WidgetHelper class

Another option is to create a class that uses strong typing and Widget identifiers to statically define which Widgets are allowed for well named parts of your application.

Here is an example of a simple helper utility:

public class WidgetHelper { public string[] HeaderWidgets() => new [] { WidgetOneIdentifier, WidgetTwoIdentifier }; public string[] FooterWidgets() => new [] { WidgetOneIdentifier }; public string[] TextWidgets() => new [] { UnstyledTextWidgetIdentifier, WYSIWYGWidgetIdentifier, CallToActionWidgetIdentifier, LinkWidgetIdentifier }; }

This WidgetHelper class can then be used to specify which Widgets are allowed for each Editable Area definition:

<div class="section"> @Html.EditableArea( // The Editable Area name "my-area-name", // The default Widget Section identifier "myDefaultSection", // The allowed Widget identifiers WidgetHelper.TextWidgets()) </div>

HtmlHelper Extensions

A third approach is to encapsulate the entire EditableArea() call inside an HtmlHelper extension method:

public static class HtmlHelperWidgetAreaExtensions { public static IHtmlString EditableHeaderArea( this ExtensionPoint<HtmlHelper> helper, string areaIdentifier) { string[] allowedWidgets = { WidgetOneIdentifier, WidgetTwoIdentifier }; return helper.EditableArea( $"header-{areaIdentifier}", HeaderDefaultSectionIdentifier, allowedWidgets); } }

This class could then be used in a view:

<div class="section"> @Html.EditableHeaderArea("my-header") </div>

This approach is great when layouts tend have common design patterns and you want your team to easily be able to define, update, and comprehend where Page Builder functionality will appear on the page ๐Ÿ‘.

Conclusion

We've covered quite a bit!

We discussed how project specific Widgets are actually very useful even though they don't feature every bit of functionality that Widgets can offer and maybe aren't that broadly reusable.

Widgets can sometimes help simplify the primary MVC types in our applications - Models, Views, and Controllers, by pulling presentation behavior out into the Widget's code.

An important thing to keep in mind when planning how Widgets should be used in an application is that they don't replace our existing tools - the content tree and custom Page Types. Forgetting this could lead to an Anti Pattern of Widget use.

Since Widgets are so easily reusable, their internal data access calls are a prime target to integrate with data caching.

Finally, we looked at a couple examples of how we can restrict Widget use through scoping.

Leave a comment below if you have any questions or ideas about creating Kentico 12 MVC Widgets.

Thanks for reading ๐Ÿ™.

[This post was originally posted, in a much longer form, on my blog on dev.to.]

If you found these tips helpful and are interested in more blog posts about Kentico 12 MVC, check out my blog over on dev.to, and if you are looking for more Kentico related developer resources, take a look at this great list over on Kentico's GitHub account!.

Share this article on   LinkedIn