When implementing custom widgets, consider implementing the following interfaces and/or an abstract base controller class:
ContentBaseController (abstract class)
Holds the main functionality for constructing all the out-of-the-box SEO properties for the widget when displaying a single item - Detail view mode. When this class is implemented, the
InitializeMetadataDetailsViewBag method can be called - pass in it the item that is currently being displayed, and based on the item and the SEO configurations of the site, Sitefinity will automatically create OG and normal SEO properties.
ContentModelBase
This class holds the auxiliary implementation for various functionality - getting content locations, creating generic list view models, creating generic details view models, creating a list view model based on a related data item, part of the implementation of the
IHasCacheDependency interface, etc.
IContentLocatableView
By implementing this interface, Sitefinity will know that a certain content type is displayed on a certain amount of pages, thus being able to determine priorities for canonical URLs:
IHasCacheDependency
The implementation of this interface will provide proper cache invalidation for the respective content type, in the custom widget, i.e. if a custom widget is displaying some items from a certain content type, and this interface is not implemented, there can be stale content displayed in the following scenario:
1. The user that is logged in is not a backend user (backend users do not have cache), or no user is logged in
2. The widget is displayed on a page, and the user has requested that page, thus the query made by the widget is cached according to the cache profile
3. An editor makes a change to an item that the widget is displaying
4. The user will not see the change until the cache expires since there is no way for Sitefinity to "know" that this item(s) are being displayed by this widget
IRouteMapper
This interface is used when one would like custom logic for resolving the route parameters. Implementing it will mean that the default behavior for MVC routing will not work but will depend only on the custom implementation. For example, there is a custom book widget (displays list of books) on a page book-catalogue. Custom routing logic can be implemented for filtering by a specific author that will resolve the desired author from the route, e.g. http://mysite/book-catalog/Index/Author
HandleUnknownAction
protected override void HandleUnknownAction(string actionName)
{
this.ActionInvoker.InvokeAction(this.ControllerContext, "Index");
}
This method is the way for Sitefinity's widgets to retain a correct state in certain scenarios - one of these is the details mode of a separate widget. In short, when a page is rendered with a widget in a mode different than the default one, Sitefinity checks all the widgets on the page if they can go into that mode. In this particular case, the news widget is going into details mode and Sitefinity is trying to push all widgets in this mode. The widgets that have Details action will get mapped earlier and Sitefinity will know not to execute them, but the widgets that do not must implement the HandleUnknownAction method so that the developer can specify what action should be executed in such a case.
Returning a view
When a view must be returned, always explicitly name the view that is going to be called.
return this.View("ViewName", viewModel);
For a full sample see the attached file to this article.