Login Status widget with external widget templates

Posted by Community Admin on 05-Aug-2018 19:01

Login Status widget with external widget templates

All Replies

Posted by Community Admin on 01-Jul-2011 00:00

It seems that it is not possible to change the LoggedInLayoutTemplatePath and LoggedOutLayoutTemplatePath properties of the LoginStatus widget. Is this a bug?

Posted by Community Admin on 04-Jul-2011 00:00

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

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

Posted by Community Admin on 05-Oct-2011 00:00

Is there any progress on resolving this?  Thanks

Posted by Community Admin on 06-Oct-2011 00:00

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

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Posted by Community Admin on 17-Nov-2011 00:00

Can you go into a bit more depth explaining the work around?

Thanks!

-Ben

Posted by Community Admin on 01-Dec-2011 00:00

@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

Posted by Community Admin on 06-Dec-2011 00:00

Hi Stevev,

You have to inherit from LoginStatusControl and override the virtual LoggedInLayoutTemplatePath and LoggedOutLayoutTemplatePath public properties.



Regards,
Ivan Dimitrov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Posted by Community Admin on 07-Feb-2012 00:00

I've tried to do this but my solution doesn't work. Can you give me an example ?

Thanks

Posted by Community Admin on 08-Feb-2012 00:00

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
            
 
        
       
    


www.sitefinity.com/.../taking_advantage_of_the_virtual_path_provider_in_sitefinity_4_1.aspx

Regards,
Ivan Dimitrov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Posted by Community Admin on 30-Nov-2012 00:00

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

Posted by Community Admin on 25-Jan-2013 00:00

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;
            
        
    

Posted by Community Admin on 28-Jan-2013 00:00

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
            
        

Please accept my apologies for the caused inconvenience.

Regards,
Veronica Milcheva
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Posted by Community Admin on 12-Apr-2013 00:00

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";
            
        
    

Posted by Community Admin on 16-Apr-2013 00:00

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:

Copy Code
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));
            
        

When OutputCache is used on the page, we substitute it with the CacheSubstitutionWrapper in DoPostCacheSubstitution() method by forming a Dictionary of parameters and passing it to a CacheSubstitutionWrapper.RenderMarkupDelegate which will later render the correct markup.

So for example in LoginStatusControl we've implemented DoPostCacheSubstitution() like this:
Copy Code
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);
        

and the delegate implementation:

Copy Code
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();
        

As you can notice from the last code excerpt above, the dynamically generated markup that will be rendered in the 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.

I hope you find the above information useful. please do not hesitate to let us know if you have any further questions, we'll be glad to help

Greetings,
Boyan Barnev
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Posted by Community Admin on 16-Apr-2013 00:00

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";

;-)

Posted by Community Admin on 19-Apr-2013 00:00

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

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Posted by Community Admin on 19-Apr-2013 00:00

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

Posted by Community Admin on 19-Apr-2013 00:00

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

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

This thread is closed