As we saw in the last post , it is possible to run server-side code by placing it directly in the Widget Template. However, although this works for quick examples, it lacks many of the conveniences of developing your template inside Visual Studio such as Intellisense and debugging.
Fortunately, it is possible to map the widget templates to external files, and in fact there are two ways to do this. Today we'll take a closer look at how this is done.
Option 1: Mapping an External Template
The first option is to edit the Widget Properties directly on the page, pointing it to your template file. For this example we'll look at the Events View widget in the Sitefinity Non-Profit Starter Kit.
Create the Template
The best way to create an external template is to copy it from an existing one. Open up the list of widget templates under the Design menu of the Sitefinity Administration backend. For this example we'll be using the DateList template for the Events - List view.
Open that template, the select everything after the first line of the template. When we create our user control, it will include it's own copy of this line, so we need to skip it when we copy the template.
Now open up your Sitefinity project in Visual Studio. Add a new User Control to your project. For organization, I recommend using a format like ~/Templates/Events/EventListTemplate.ascx. Paste the markup from the widget template into the control.
If you are using a Web Application Project, there is one important change you need to make. You see, templates are loaded dynamically by Sitefinity instead of being compiled into your project. As a result the user control must be modified to behave as a Web Site Project User Control so that it can behave as such when it is loaded.
Fortunately this is easy to do. Simply change the CodeBehind property on the first line of the .ascx control to instead be CodeFile. Now when the template is loaded, it will also load the associated code-behind file, meaning you no longer have to use the <script> tag as we did last time!
Map the Template
Now that we've created the external template, we need to tell the widget to use it. In this starter kit, the events view widget is on the ~/Events page, so open it up in the Sitefinity administration and edit the widget and click the "Advanced" button.
Now click the ControlDefinition button, then on the next page click the Views to see the two views for the widget.
We want to edit the EventsFrontendList view, so click that button and scroll down to see the TemplateName and TemplatePath properties.
Simply set the path to your .ascx file in the TemplatePath property to point the view for the widget to the template.
Important Note: The Guid in the TemplateKey corresponds to the ID of the internal Sitefinity Widget Template. This property does take priority over the TemplatePath value, so be sure to delete the Guid so that the property is blank or it will continue to use the internal template instead.
Save your changes and publish the page and you'll now see that the template is loading from your external file.
Option 2: Using the Virtual Path Provider
As mentioned by Slavo in the previous post Taking advantage of the Virtual Path Provider in Sitefinity 4.1, the new Virtual Path Provider simplifies loading of internal and external resources. We can use this to our advantage when mapping external templates.
The way that the VPP works for Widget Templates is through the virtual path ~/SfCtrlPresentation/[PageProviderName],[TemplateGuidWithoutDashes].ascx. This means it's looking for the template in the virtual "folder" named SfCtrlPresentation that follows the naming convention that matches the template.
If we want to override the internal templates, we simply need to create this actual folder and place inside it a template that matches that naming convention.
More than likely you are using the Default Page Provider for Sitefinity, so the PageProviderName should be OpenAccessDataProvider. The Template Guid corresponds to the TemplateKey property we saw above, except with the dashes stripped out.
So to use the Virtual Path Provider, instead of deleting the TemplateKey property and setting the TemplatePath, we leave the TemplateKey property in place and use that Guid for the external template name, removing the dashes.
That means for this widget template, we'll create the SfCtrlPresentation folder, then inside it create a new User Control and name it OpenAccessDataProvider,c2b52ad7acaa4838a3c695a275a8f014.ascx.
Note that the comma is required as part of the name of the template file.
As before, change the CodeBehind property of the User Control to CodeFile. Now when you visit the Events page, it should load the physical template file, overriding the Virtual Path it would otherwise use if it didn't exist.
Clearly working with the internal naming convention is slightly cumbersome, and improvements to this process are already in the works so that using the VPP to map templates is simpler and more intuitive. However this does allow you to create a direct mapping from an internal template to an external file.
In addition, remember that the Guid used corresponds to the ID of the internal Widget Template, and this template needs to be assigned to the Widget in order for it to be loaded correctly. If you change the view to use a different internal template, the Guid will change and your template will not be loaded. This too is already being addressed by the development team.
Feedback and What's Next
To close of this discussion on templates, I'll be posting a quick 5 things post later this week on some of the additional benefits you gain from using external templates.
I also strongly encourage you to try playing with external templates yourself in your Sitefinity projects and especially to report your feedback via our Sitefinity 4 discussion forum. This is a new way to hook into additional opportunities for customization, so we want to know how you're using it and how it can be improved.