{"id":50,"date":"2011-08-30T12:12:35","date_gmt":"2011-08-30T16:12:35","guid":{"rendered":"http:\/\/blogs.visigo.com\/chriscoulson\/?p=50"},"modified":"2011-08-30T12:12:35","modified_gmt":"2011-08-30T16:12:35","slug":"loadtemplate-and-the-asp-net-login-controls","status":"publish","type":"post","link":"https:\/\/blogs.visigo.com\/chriscoulson\/loadtemplate-and-the-asp-net-login-controls\/","title":{"rendered":"LoadTemplate and the ASP.NET Login controls"},"content":{"rendered":"<p>Recently I was trying to programmatically load the templates for the PasswordRecovery control. I thought it should be pretty straightforward:<\/p>\n<ul>\n<li>Put the contents of the template in an ascx file<\/li>\n<li>Assign passwordRecovery.UserNameTemplate to Page.LoadTemplate(&#8220;MyUserNameTemplate.ascx&#8221;)<\/li>\n<\/ul>\n<p>Should be a piece of cake right? Wrong.<\/p>\n<p>If the template is put directly in the ASPX page all works as expected. \u00a0If the same template is loaded using LoadTemplate, you&#8217;ll get an error like:<\/p>\n<blockquote><p>UserNameTemplate does not contain an IEditableTextControl with ID UserName for the username<\/p><\/blockquote>\n<p>After some sleuthing I realized the problem was in the way LoadTemplate adds the loaded template controls. \u00a0LoadTemplate (which returns an ITemplate of type SimpleTemplate) adds the loaded template to a parent control, and then adds that parent control to the container. \u00a0The login controls search the container for the required controls using FindControl. Since the container only contains the parent control, the required controls (which are in the parent control) are not found.<\/p>\n<p>The solution was to create my own class derived from ITemplate. \u00a0The class loads the template into a temporary container using the LoadTemplate method. \u00a0Then it moves the child controls from the parent control in the temporary container into the destination container. Here&#8217;s the code:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/\/ &lt;summary&gt; \r\n\/\/\/ Loads a template from an ASCX, but unlike SimpleTemplate adds controls directly to the specified container so that it will work with ASP.NET Login Controls\r\n\/\/\/ (SimpleTemplate adds the controls to a parent control and adds the parent control to the container)\r\n\/\/\/ &lt;\/summary&gt;\r\npublic class TemplateLoader : ITemplate\r\n{\r\n\tprivate string _virtualPath;\r\n\tprivate Page _page;\r\n\r\n\tpublic TemplateLoader(string virtualPath, Page page)\r\n\t{\r\n\t\t_virtualPath = virtualPath;\r\n\t\t_page = page;\r\n\t}\r\n\r\n\tvoid ITemplate.InstantiateIn(Control container)\r\n\t{\r\n\t\tITemplate template = _page.LoadTemplate(_virtualPath);\r\n\t\tControl tempContainer = new Control();\r\n\t\ttemplate.InstantiateIn(tempContainer);\r\n\r\n\t\twhile (tempContainer.Controls&#x5B;0].HasControls())\r\n\t\t{\r\n\t\t\tcontainer.Controls.Add(tempContainer.Controls&#x5B;0].Controls&#x5B;0]);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>And to use:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n_ctlPasswordRecovery.UserNameTemplate = new TemplateLoader(&quot;\/_layouts\/FBA\/templates\/PasswordRecoveryTemplate.ascx&quot;, Page);\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Recently I was trying to programmatically load the templates for the PasswordRecovery control. I thought it should be pretty straightforward: Put the contents of the template in an ascx file Assign passwordRecovery.UserNameTemplate to Page.LoadTemplate(&#8220;MyUserNameTemplate.ascx&#8221;) Should be a piece of cake right? Wrong. If the template is put directly in the ASPX page all works as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[96,110],"tags":[321,114,94,116,111,95,126,112,113,125,103,118,127,128,121,119,124,123,122,21,120,115,117],"class_list":["post-50","post","type-post","status-publish","format-standard","hentry","category-net","category-asp-net-net","tag-net","tag-ascx-file","tag-asp-net","tag-aspx","tag-aspx-page","tag-c","tag-changepassword","tag-control-container","tag-control-template","tag-createuserwizard","tag-csharp","tag-instantiatein","tag-itemplate","tag-loadtemplate","tag-login","tag-login-controls","tag-loginname","tag-loginstatus","tag-loginview","tag-membership","tag-passwordrecovery","tag-templates","tag-usernametemplate"],"_links":{"self":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/posts\/50","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/comments?post=50"}],"version-history":[{"count":0,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/posts\/50\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/media?parent=50"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/categories?post=50"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/tags?post=50"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}