LayoutControl Templates need the Provider fix?
Do the layout controls need to follow this format for the new providers?
I keep getting
Hi Steve,
You could get this error if the template does not start with "~/" or "<" and does not end with .ascx
This happens when we render the page and build the controls on it.
Kind regards,
Ivan Dimitrov
the Telerik team
Well I updated the "Name" like the blog post suggested
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
Telerik.Sitefinity.Web.UI;
namespace
OCFP.Controls.Layouts
public
class
InfoPod : LayoutControl
public
override
string
Layout
get
return
this
.CustomTempalate;
public
override
string
AssemblyInfo
get
return
GetType().ToString();
set
base
.AssemblyInfo = value;
protected
override
void
CreateChildControls()
base
.CreateChildControls();
public
string
CustomTempalate =
"~/OCFP/OCFP.Layouts.Views.InfoPod.ascx"
;
Hi Steve,
I remember that there was an issue with the Layout property and it should be overridden as shown below
public override string Layout
get
var layout = this.ViewState["Layout"] asstring;
if(string.IsNullOrEmpty(layout))
layout = this.CustomTempalate;
return layout;
Regards,
Ivan Dimitrov
the Telerik team
Has this been resolved? I am having the same issue, when I go to the live page I get the "Invalid Layout Template" error. I tried the code sample provided, setting the Layout string to whatever is in the ViewState unless it is null or empty and that didn't fix the issue.
Hello Leng,
Yes there is no issue with the custom layouts if they are implemented properly! I am sending you a simple implementation and short video that shows all settings that you need to get this working
1. Class
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
Telerik.Sitefinity.Web.UI;
namespace
Telerik.Sitefinity.Samples
public
class
LayoutControlCustom : LayoutControl
public
override
string
Layout
get
var layout =
this
.ViewState[
"Layout"
]
as
string
;
if
(
string
.IsNullOrEmpty(layout))
layout =
this
.CustomTempalate;
return
layout;
public
override
string
AssemblyInfo
get
return
GetType().ToString();
set
base
.AssemblyInfo = value;
public
string
CustomTempalate =
"~/MyPRefix/Telerik.Sitefinity.Samples.Resources.SixColumnLayout.ascx"
;
<%@ Control Language="C#" %>
<
div
id
=
"Div1"
runat
=
"server"
style
=
"width:960px; margin-left: 20px;"
class
=
"sf_cols"
>
<
div
id
=
"Div2"
runat
=
"server"
style
=
"float: left; width: 154px; margin: 0; "
class
=
"sf_colsOut"
>
<
div
id
=
"Div3"
runat
=
"server"
style
=
"width: 150px; margin-right: 4px; text-align: center;"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
<
div
id
=
"Div4"
runat
=
"server"
style
=
"float: left; width: 154px; margin: 0; "
class
=
"sf_colsOut"
>
<
div
id
=
"Div5"
runat
=
"server"
style
=
"width: 150px; margin-right: 4px; text-align: center;"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
<
div
id
=
"Div6"
runat
=
"server"
style
=
"float: left; width: 154px; margin: 0; "
class
=
"sf_colsOut"
>
<
div
id
=
"Div7"
runat
=
"server"
style
=
"width: 150px; margin-right: 4px; text-align: center;"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
<
div
id
=
"Div8"
runat
=
"server"
style
=
"float: left; width: 154px; margin: 0; "
class
=
"sf_colsOut"
>
<
div
id
=
"Div9"
runat
=
"server"
style
=
"width: 150px; margin-right: 4px; text-align: center;"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
<
div
id
=
"Div10"
runat
=
"server"
style
=
"float: left; width: 154px; margin: 0; "
class
=
"sf_colsOut"
>
<
div
id
=
"Div11"
runat
=
"server"
style
=
"width: 150px; margin-right: 4px; text-align: center;"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
<
div
id
=
"Div12"
runat
=
"server"
style
=
"float: left; width: 154px; margin: 0; "
class
=
"sf_colsOut"
>
<
div
id
=
"Div13"
runat
=
"server"
style
=
"width: 150px; margin-right: 4px; text-align: center;"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
</
div
>
Hey Ivan,
I was told in a ticket that the layouts are not supposed to have IDs specified anymore (in 4.1)....is that not the case now?
Hi Steve,
If you add the IDs this will not break the custom layout control. You can remove the IDs from the divs
Greetings,
Ivan Dimitrov
the Telerik team
Ok great, so doesn't matter if they're named "Div1, Div2, Div3" or "Container1, Container2, Container3" then right?
Also, what's with the inline style tags now? Is that just to illustrate this sample, or are inline styles now a requirement?
Hey Ivan,
I honestly believe that I have correctly implemented code to create my own Custom Layout control just as you have provided in your examples. The reason I believe this to be the case is because I can go into Edit mode on a page and go select my custom layout and drop it onto the page. I can see the Layout Element as it is supposed to appear. I can then add controls into the Widget slots on that layout and even click the preview button and see everything appear correctly. It is only when I click "Publish" and go to the live page that I get an "Invalid Layout Template" error. If I can see the custom layout control and I can drag and drop it and I can preview it, I honestly do not think that I am incorrectly referencing it with my configured virtual path. That appears to be the only thing that changed between 4.0 and 4.1 in terms of implementing this control.
Regardless, for anyone who is still having problems, I have discovered a work-around that gets your Custom Layout control to work. If you follow this one vital step, it fixes the "Invalid Layout Template" error. What you have to do is, after you've placed your custom layout element onto the page you are editing, you have to click on the "Edit" button in the top right corner of the layout control. You'll get the toolbox on the right to adjust the widths of each column you have, don't actually change any of the widths here, as it'll mess up your layout. Just simply click the "Done" button to save out the layout control that is on the page. This fixes the problem. What I think is happening is that when you edit the template, the HTML markup that you have in the .ascx file you've embedded is parsed by the Sitefinity services when it is saving it to the database as part of the page you're editing. This parsing somehow does whatever is required to save the HTML markup in a way that Sitefinity can then serve it up later on the live page. You have to do this for every custom layout element that you drop onto the page.
Hope that helps everyone out who's experiencing this frustrating problem.
Thanks for finding that workaround...pain in the ass to go though every page though :/
Hello Leng,
"I honestly believe that I have correctly implemented code to create my own Custom Layout control just as you have provided in your example"
The error you get is because of the implementation of the virtual path provider. Also the Layout property needs to be implemented as shown on the video and I must that this you have not done it in this way. When the references to the virtual path provider are not properly set and the static string is also not set in the custom layout control, the template could not be found. Some of the changes in the configurations require application restart so if you haven't done this the error could keep appearing at your end. As you can see from the attached video the control works just fine.
Greetings,
Ivan Dimitrov
the Telerik team
Ivan,
Are you saying that the error I am receiving is because of how Telerik has implemented the virtual path provider or are you saying that I have not properly setup the virtual path provider? If I have not setup the virtual path provider correctly, then I want you to answer just a few simple questions. Why is that when I am in Edit mode and Preview mode for the page I am placing my custom layout control onto, I can see the layout control perfectly fine and I get no errors what so ever? It is only when I view the published page, that I get this error? If the virtual path provider is not setup correctly, wouldn't I get an error every time I view the page, whether in Edit, Preview or Published mode? Why does my page work if I edit my custom layout control through the Sitefinity GUI without actually changing any of the properties or values?
I don't want to get into a shouting match about what I've done right and what I've done wrong. All I know is I setup a virtual path in the configuration just as the blog posts that has been mentioned several times suggests. I have also tried setting up the static string in the custom layout control and that has not resolved this error.
I want to thank you though, for taking the time to respond and providing help.
Leng
Hmm yeah same...I don't remember the blog post mentioning anything about updating a Admin config entry
It's saying we need to put stuff in Global.asax...and the video shows the entries being created in the config directly...
I would prefer to NOT have to distribute controls telling people to add a Global.asax or lines to an existing Global.asax if I don't have to...so the blog post is then dynamically adding in the entry to the xml? Is that what I'm seeing? I'm just confused as to why we would do that over just editing the config directly...is it that the external .config doesn't exist until this runs?
But like Leng, we've followed all documentation to the letter as far as we know.
When the service pack is released at the end of the week I'll perhaps try this again...I've rolled back to 1238 right now because I can't use 4.1 just yet.
Hey Steve,
If you read the comments in that blog post by Slavo, you will see that someone asked about why this needed to be done in the Global.asax? He responded by saying that it could also be done in the Administration Settings section of Sitefinity if you wanted to do it there instead.
Leng
Thanks Ivan, This works like a charm form me following your steps.
Is there a fix on this issue? i still keep getting the "Invalid layout template." Error.
Pre 4.1 it worked all fine. Where is the bug? All help is appreciated. I am at a dead end.
Thanks in advance.
<%@ Control Language="C#" %>
<
div
style
=
""
runat
=
"server"
class
=
"sf_cols"
>
<
div
style
=
""
runat
=
"server"
class
=
"line innovationLine"
>
<
div
style
=
""
class
=
"unit teaserHomeInnovation"
>
<
div
style
=
""
class
=
"mod modHomeInnovationTeaser"
>
<
div
style
=
""
class
=
"inner"
>
<
div
style
=
""
class
=
"bd sf_cols"
>
<
div
style
=
""
class
=
"innovation-wrapper sf_colsOut"
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn pics"
>
</
div
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn txt-wrapper"
>
</
div
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn txt-wrapper last"
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
style
=
""
class
=
"unit teaserHomeCustomer lastUnit"
>
<
div
style
=
""
class
=
"mod modHomeCustomerPortal"
>
<
div
style
=
""
class
=
"inner"
>
<
div
style
=
""
class
=
"bd sf_cols"
>
<
div
style
=
""
class
=
"customer-wrapper sf_colsOut"
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn txt-wrapper"
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsOut line boxLine"
>
<
div
style
=
""
class
=
"unit teaserHomeContent"
>
<
div
style
=
""
class
=
"mod modHomeContentTeaser sf_cols"
>
<
div
style
=
""
class
=
"inner sf_colsOut"
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn bd"
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
style
=
""
class
=
"unit teaserHomeContent"
>
<
div
style
=
""
class
=
"mod modHomeContentTeaser sf_cols"
>
<
div
style
=
""
class
=
"inner sf_colsOut"
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn bd"
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
style
=
""
class
=
"unit teaserHomeContent"
>
<
div
style
=
""
class
=
"mod modHomeContentTeaser sf_cols"
>
<
div
style
=
""
class
=
"inner sf_colsOut"
>
<
div
style
=
""
runat
=
"server"
class
=
"sf_colsIn bd"
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
style
=
""
runat
=
"server"
class
=
"unit teaserHomeNews lastUnit sf_colsIn"
>
</
div
>
</
div
>
</
div
>
namespace
ABCInternetWebApp.Custom.Layouts
using
Telerik.Sitefinity.Web.UI;
/// <summary>
/// The Home layout.
/// </summary>
public
partial
class
HomeLayout : LayoutControl
#region Constants and Fields
/// <summary>
/// The custom template.
/// </summary>
private
const
string
CUSTOMTEMPLATE =
"~/Custom/Layouts/HomeLayout.ascx"
;
#endregion
#region Properties
/// <summary>
/// Gets or sets AssemblyInfo.
/// </summary>
public
override
string
AssemblyInfo
get
return
GetType().ToString();
set
base
.AssemblyInfo = value;
/// <summary>
/// Gets the Layout.
/// </summary>
public
override
string
Layout
get
var layout = ViewState[
"Layout"
]
as
string
;
if
(
string
.IsNullOrEmpty(layout))
layout = CUSTOMTEMPLATE;
return
layout;
#endregion
Hi ,
As far as I see you don't use the virtual path provider (VPP).
Greetings,
Ivan Dimitrov
the Telerik team
Hi Ivan, I followed the steps word for word except the ones that state where to put the .cs and .ascx files on the actual file directory because I don't see them anywhere. Anyway after following everything including even the naming convention, whenever I drag the newly-created Layout Control, this thing prompts:
Could not load file or assembly 'Telerik.Sitefinity.Samples' or one of its dependencies. The system cannot find the file specified.
Hi Leng, your workaround worked with the solution we worked with the 4.0 version that did not require the VPP thing. My only scare is it might not work anymore upon deployment to production. How is your experience, is it stable enough?
Hello Jkregala,
The error says that the namespace used for registering the control is not correct. You don't have Telerik.Sitefinity.Samples.dll in your project or this class library is not referenced to the web application.
All the best,
Ivan Dimitrov
the Telerik team
Hey Jkregala,
The work around so far for us has not presented any issues. We upgraded to the latest service pack, SP 1 which is supposed to have fixed the issue, but we have not revisited the layouts since we got them working. Currently, our custom layouts with the work-around work in our dev environments, staging and test environments. My opinion is that if your layout is absolutely necessary for your site to function, there is no other way to get it to work as far as I have seen, so it is the only viable option at the moment.