Login Status widget with external widget templates
It seems that it is not possible to change the LoggedInLayoutTemplatePath and LoggedOutLayoutTemplatePath properties of the LoginStatus widget. Is this a bug?
Hello Nelson,
Yes, there is a know issue about the template paths of the control. I suggest that you should use the standard ASP.NET analogs in a custom or user controls as a workaround.
Greetings,
Ivan Dimitrov
the Telerik team
Is there any progress on resolving this? Thanks
Hi Ian,
The status of the issue is not fixed. There is a workaround that I see if you override
LoggedInLayoutTemplatePath and LoggedOutLayoutTemplatePath, but changing the properties though the control designer does not work.
Regards,
Ivan Dimitrov
the Telerik team
Can you go into a bit more depth explaining the work around?
Thanks!
-Ben
@Ivan:
Per your last post: "There is a workaround that I see if you override
LoggedInLayoutTemplatePath and LoggedOutLayoutTemplatePath, but changing the properties though the control designer does not work."
The "LoggedInLayoutTemplatePath" and "LoggedInLayoutTemplatePath" values aren't persisted when edited via the designer. Any info on the work around would be appreciated.
Thanks--Steve
Hi Stevev,
You have to inherit from LoginStatusControl and override the virtual LoggedInLayoutTemplatePath and LoggedOutLayoutTemplatePath public properties.
Regards,
Ivan Dimitrov
the Telerik team
I've tried to do this but my solution doesn't work. Can you give me an example ?
Thanks
Hi,
Here is a sample code
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
Telerik.Sitefinity.Web.UI.PublicControls;
namespace
SitefinityWebApp
public
class
LoginStatusControlSample : LoginStatusControl
protected
override
string
LoggedInLayoutTemplateName
get
return
null
;
protected
override
string
LoggetOutLayoutTemplateName
get
return
null
;
public
override
string
LoggedInLayoutTemplatePath
get
return
"~/MyPRefix/Telerik.Sitefinity.Samples.Resources.LoggedInLayoutTemplatePath
.ascx
"
;
// here return your template using Virtual Path provider
public
override
string
LoggedOutLayoutTemplatePath
get
return
"
~/MyPRefix/Telerik.Sitefinity.Samples.Resources.LoggedOutLayoutTemplatePath
.ascx"
;
"
;
//here return your template using Virtual Path provider
Anyone else experiencing this issue... lets vote it up so they'll finally fix it. Still an issue in the latest version a year and a half later... only now the workaround doesn't even work it seems.
www.telerik.com/.../pits.aspx
I overrode all three functions below, the designer is working fine but I still can't get the right template to show. Any update on this?
public class LoginStatusControl : Telerik.Sitefinity.Web.UI.PublicControls.LoginStatusControl
private string _LoggedInLayoutTemplatePath;
private string _LoggedOutLayoutTemplatePath;
[Browsable(false)]
public override string LayoutTemplatePath
get
if (!this.IsLoggedIn)
return this.LoggedOutLayoutTemplatePath;
return this.LoggedInLayoutTemplatePath;
set
[WebDisplayName("DisplayName_LoggedInLayoutTemplatePath"), Telerik.Sitefinity.Web.UI.PublicControls.Attributes.WebCategory("ControLCategory_Templates")]
public override string LoggedInLayoutTemplatePath
get
if (_LoggedInLayoutTemplatePath.IsNullOrEmpty())
return ControlUtilities.ToVppPath("Telerik.Sitefinity.Resources.Templates.PublicControls.LoginStatus_LoggedIn.ascx");
else
return _LoggedInLayoutTemplatePath;
set
base.LayoutTemplatePath = value;
_LoggedInLayoutTemplatePath = value;
[WebDisplayName("DisplayName_LoggedOutLayoutTemplatePath"), Telerik.Sitefinity.Web.UI.PublicControls.Attributes.WebCategory("ControLCategory_Templates")]
public override string LoggedOutLayoutTemplatePath
get
if (_LoggedOutLayoutTemplatePath.IsNullOrEmpty())
return ControlUtilities.ToVppPath("Telerik.Sitefinity.Resources.Templates.PublicControls.LoginStatus_LoggedOut.ascx");
else
return _LoggedOutLayoutTemplatePath;
set
base.LayoutTemplatePath = value;
_LoggedOutLayoutTemplatePath = value;
Hi,
Unfortunately this is not fixed yet. I'll increase the priority of the PITS and we'll do out best to fix it in one of our next Releases.
As for your solution - you should better override the LayoutTemplateName property and use the same logic as in the LayoutTemplatePath:
protected
override
string
LayoutTemplateName
get
return
this
.IsLoggedIn ?
this
.LoggedInLayoutTemplateName :
this
.LoggetOutLayoutTemplateName;
public
override
string
LayoutTemplatePath
get
return
this
.IsLoggedIn ?
this
.LoggedInLayoutTemplatePath :
this
.LoggedOutLayoutTemplatePath;
set
// does nothing
Veronica your suggested code doesn't seem to work.
Here is what I use but my controls never get displayed....
using System;
using System.Linq;
using Telerik.Sitefinity.Web.UI.PublicControls;
namespace SitefinityWebApp.CustomWidgets.Login
public class CustomLoginStatus : LoginStatusControl
protected override string LayoutTemplateName
get
return this.IsLoggedIn ? this.LoggedInLayoutTemplateName : this.LoggetOutLayoutTemplateName;
public override string LayoutTemplatePath
get
return this.IsLoggedIn ? this.LoggedInLayoutTemplatePath : this.LoggedOutLayoutTemplatePath;
set
// does nothingv dsf
protected override string LoggedInLayoutTemplateName
get
return "~/SfLocal/SitefinityWebApp.CustomWidgets.Login.LoginStatus_LoggedIn.ascx";
protected override string LoggetOutLayoutTemplateName
get
return "~/SfLocal/SitefinityWebApp.CustomWidgets.Login.LoginStatus_LoggedOut.ascx";
public override string LoggedInLayoutTemplatePath
get
return "~/SfLocal/SitefinityWebApp.CustomWidgets.Login.LoginStatus_LoggedIn.ascx";
public override string LoggedOutLayoutTemplatePath
get
return "~/SfLocal/SitefinityWebApp.CustomWidgets.Login.LoginStatus_LoggedOut.ascx";
Hello Ivan,
To address our client feedback where in some cases the LoginStatus control was displaying the cahced HTML and did not update its staus correclty we have implemented cache subsitution for that control. In other words, the LoginStatus control does not use the LayoutTemplatePath
property to resolve the markup that should be rendered anymore.
Let me quickly elaborate a bit on the above statement:
For each control inheriting from System.Web.UI.WebControls.WebControl we can override the RenderContents(System.Web.UI.HtmlTextWriter writer) method and in it we call our own implementation for performing cache substitution.
In LoginStatusControl, for example we have:
protected
override
void
RenderContents(System.Web.UI.HtmlTextWriter writer)
if
(!SystemManager.IsDesignMode)
this
.DoPostCacheSubstitution();
else
writer.WriteEncodedText(Res.Get<PublicControlsResources>().ControlCannotBeRenderedInDesignMode.Arrange(Res.Get<PublicControlsResources>().LoginStatusControlTitle));
private
void
DoPostCacheSubstitution()
Dictionary<
string
,
string
> parameters =
new
Dictionary<
string
,
string
>();
parameters.Add(
"ShowLoginName"
,
this
.ShowLoginName.ToString());
parameters.Add(
"LoginNameFormatString"
,
this
.LoginNameFormatString);
parameters.Add(
"ClientId"
, ((LinkButton)
this
.StatusButton).UniqueID);
Page.ClientScript.RegisterForEventValidation(((LinkButton)
this
.StatusButton).UniqueID);
CacheSubstitutionWrapper cacheSubstitutionWrapper =
new
CacheSubstitutionWrapper(parameters,
new
CacheSubstitutionWrapper.RenderMarkupDelegate(LoginStatusControl.RenderCacheSubstitutionMarkup));
cacheSubstitutionWrapper.RegisterPostCacheCallBack(
this
.Context);
internal
static
string
RenderCacheSubstitutionMarkup(Dictionary<
string
,
string
> parameters)
bool
isUserLoggedIn =
false
;
ClaimsIdentityProxy user = ClaimsManager.GetCurrentIdentity();
if
(user !=
null
)
isUserLoggedIn = user.IsAuthenticated;
StringBuilder resultMarkup =
new
StringBuilder();
if
(isUserLoggedIn)
bool
showLoginName =
bool
.Parse(parameters[
"ShowLoginName"
]);
if
(showLoginName)
string
formatedUserName = LoginNameControl.FormatLoginName(parameters[
"LoginNameFormatString"
]);
resultMarkup.Append(formatedUserName);
resultMarkup.AppendFormat(@
" <a href="
"javascript:__doPostBack('0','')"
" >1</a>"
, parameters[
"ClientId"
].ToString(), Res.Get<PublicControlsResources>().LogOutText);
else
resultMarkup.AppendFormat(@
" <a href="
"javascript:__doPostBack('0','')"
" >1</a>"
, parameters[
"ClientId"
].ToString(), Res.Get<PublicControlsResources>().LogInText);
return
resultMarkup.ToString();
CacheSubstitutionWrapper
is loaded from the LogInText
and LogOutText
localizable resources of the PublicControlsResources
(you can edit these from Administration -> Interface labels and messages). You can either modify their values or inherit from the control, and override the above listed methods, so you can plug in your custom markup.Hi Boyan,
yes that's also what was posted by Patrick Dunn on his blog, it's not a very nice nor elegant solution, and I already brought other's attention to a potential problem with the beginning of that RenderCacheSubsitutionMarkup method:
ClaimsIdentityProxy user = ClaimsManager.GetCurrentIdentity();
will not be null even if its an unauthenticated user. ClaimsManager returns a user object anyway the only difference is that user.Name = "Anonymous";
;-)
Hello Ivan,
Thnak you for your feedback. Can you please elaborate a bit on the potential problem you've spotted with that call, so we can inspect it further if necessary?
Please note that the logical switch on the following line is actually targeted towards determining the user.IsAuthenticated value, so the check for null if just a standard defense programming - we do not expect the user to be null when the currently browsing user is not authenticated, but we need to ensure we've retrieved the ClaimsIdentityProxy object, before checking its IsAuthenticated property.
Regards,
Boyan Barnev
the Telerik team
Hi Boyan,
my wrong. I expected an unauthenticated visitor to be null, now I get it, you get back a user (of type ClaimsIdentityProxy ) for unauthenticated users to and then you check wether they are authenticated or not. I was surprised to see that no null user is returned for unauthenticated users. You can freely delete my former post as it might be misguiding others then.
Thanks Boyane,
Ivan
Hi Ivan,
No problems at all, we highly value your constructive feedback you've been providing us with, and just wanted to make sure where there wasn't an actual problem worth researching. I'm really glad to hear that everything has been sorted now.
Greetings,
Boyan Barnev
the Telerik team