Implementation Plugin (UserControl) based system in ASP WebForm - asp.net

I have many UserControls and I wanna load them depended on query string in one aspx page.
I tired 2 following ways:
Add a Placeholder in aspx page and in Page_Load/Page_Render event:
UserControl uc = (UserControl)LoadControl("/PATH/ProductGroups.ascx");
phMain.Controls.Add(uc);
Add a MasterPage, then add an aspx and using of masterpage, then register the UserControl on the aspx
But in both, I got following error:
The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
BTW, I have used telerik TextEditor in the loaded UserControl.
How I can handle that?
I think the only way that I have, multiple aspx per UserContorl, without MasterPage, this is sucks, as you know ! because I have to fix HTML/CSS/JS in all pages, one by one and this is not pro !
NOTE: without using telerik TextEditor, everything working fine, but I need this one, also this wat (loading UserControl in PlaceHolder) is not really good way.
I'm looking for something like DNN.

I tried to replicate this error, but i couldn't. It is just working fine for me. Here is what I tried in VS2013.
1) Added MasterPage
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="Test.Site1" %>
<%# Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<telerik:RadScriptManager ID="RadScriptManager1" runat="server"></telerik:RadScriptManager>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
2)Added WebUserControl
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="Test.WebUserControl1" %>
<%# Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<telerik:RadEditor runat="server" ID="RadEditor1" SkinID="DefaultSetOfTools" Height="675px">
</telerik:RadEditor>
3) Added WebForm
<%# Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="Test.WebForm3" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:PlaceHolder runat="server" ID="phMain" />
</asp:Content>
4) Loaded the control
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Test
{
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
UserControl uc = (UserControl)LoadControl("~/WebUserControl1.ascx");
phMain.Controls.Add(uc);
}
}
}
Here is the resolution for the error "Control collection cannot be modified"

Related

ASP.NET ContentPage with Form Controls

I created a content page that references a master page. In the content page I have a form and some form controls with a submit button. When I hit submit though the parameters are not detected on page load in the content page. On top of that the name of the parameters are all messed up.
What is the correct way of adding form controls to the content page and then using Request.QueryString[ID]?
I just realized that Microsoft throws all kinds of extra crap at you when you use master pages. It is absolutely ridiculous, is there a way for me not to go down this route of using all kinds of silly casting and inefficient overhead:
http://www.asp.net/web-forms/tutorials/master-pages/control-id-naming-in-content-pages-cs
My code (MASTER PAGE):
<%# Master Language="C#" AutoEventWireup="true" ClientIDMode="Static" %>
<!DOCTYPE html>
<html lang="en">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="Head" runat="server"></asp:ContentPlaceHolder>
</head>
<body>
<asp:ContentPlaceHolder runat="server" ID="MainContent" />
</body>
</html>
My code (Content Page):
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
<label for="iSiteId">Site Id(s)</label>
<asp:TextBox ID="iSiteId" runat="server"></asp:TextBox>
<label for="iVersion">Version(s)</label>
<asp:TextBox ID="iVersion" runat="server"></asp:TextBox>
</asp:Content>
My Code (Content Page but the Code behind)
_siteId = Request.QueryString["iSiteId"];
_categoryId = Request.QueryString["iCategoryId"];
_version = Request.QueryString["iVersion"];
Try these instead:
siteId = iSiteId.Text;
_categoryId = iCategoryId.Text;
_version = iVersion.Text;

ASP.NET Page / MasterPage life cycle

Trying to understand how after MasterPage render, the content of Page already exists in HtmlTextOutput?
ASP.NET, first calling Page.Render, then Page renders it's children controls and MasterPage is in theory "child control" of page. If so, how then after MasterPage.Render completes it contains the output for all other child controls of Page? How Master.Render, "calls" render of page itself and it's child controls?
Example:
MasterPage:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="MAIN.master.cs" Inherits="Demo.MAIN" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
ContentPlaceHolder - BEFORE
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
ContentPlaceHolder - AFTER
</div>
</form>
</body>
</html>
public partial class MAIN : System.Web.UI.MasterPage
{
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
//At this point HtmlTextWriter already contains the output of all page child controls...how it's happen?
}
Page:
<%# Page Title="" Language="C#" MasterPageFile="~/MAIN.Master" AutoEventWireup="true" CodeBehind="MAIN_PAGE.aspx.cs" Inherits="Demo.MAIN_PAGE" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
CONTENT
<TL:MyButton id="ServerControl" Text="btn" runat="server"/>
</asp:Content>
public partial class MAIN_PAGE : MyPage
{
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
}
}

ASP.NET putting a control in a C# <%= Function(<control/>) %>

I know you can't put a control inside a C# function like this
<%= VirtualPathUtility.ToAbsolute(<umbraco:Item field="background" runat="server" />) %>
but I am wondering if you can pass the value from a control to a C# function.
umbraco:Item above outputs something like ~/media/bg1.jpg
Here is what I am trying to do:
<%# Master Language="C#" MasterPageFile="/masterpages/Master.master" AutoEventWireup="true" %>
<asp:content ContentPlaceHolderId="cphHead" runat="server">
<style type="text/css">
#content {
background: url('<%=VirtualPathUtility.ToAbsolute(<umbraco:Item field="background" runat="server" />)%>');
}
</style>
</asp:content>
Anyone know any solution? Thanks in advance.
If it's just a plain textstring then you can do the following:
<%# Master Language="C#" MasterPageFile="/masterpages/Master.master" AutoEventWireup="true" %>
<%# Import Namespace="umbraco" %>
<%# Import Namespace="umbraco.presentation" %>
<%# Import Namespace="umbraco.presentation.nodeFactory" %>
<asp:content ContentPlaceHolderId="cphHead" runat="server">
<style type="text/css">
#content {
background: url('<%=VirtualPathUtility.ToAbsolute(Node.GetCurrent().GetProperty("background").Value)%>');
}
</style>
</asp:content>
However, if the "background" property is a media picker then you need a little more help than just that, which will involve the umbraco.cms.businesslogic.media namespace. I suggest you check out the libraries with Reflector, or the source code repository on Codeplex to find out the classes you should be using and how to subsequently populate your property.
HTH,
Benjamin

css stopped working asp.net

I am reposting the question, since it has changed a lot since I had problems with it initially, I know where the problem is but i do not know how to fix it, or the cause of it at all.
So i have 2 master files, one is for a login page and another one for the inside content. I also have a default.aspx file and a logout.aspx file. They both use the MasterPage.master which is the initial page. What i found out is, when I exclude the Logout.aspx from the project and run it, the website initial page uses the .css file. When I include the logout.aspx debug the program, the initial screen uses the .css at first then when i log in and log out, it shows the default.aspx without the .css. If I try to debug the page again, then the initial screen no longer uses the .css.
My master class has this:
<%# Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="~/StyleSheet.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form runat="server">
<div class="login">
<div class="container">
<div class="header">
<h1 id="site-name">
<font color="black" size="5">SES Users Admin</font>
</h1>
</div>
<!--Hello Content -->
<div class="content">
<asp:Label ID="lblUsername" runat="server" Text="Username"></asp:Label>
<asp:TextBox ID="txtUsername" runat="server" Height="21px"
style="margin-left: 2px" Width="133px"></asp:TextBox>
<br /><br />
<asp:Label ID="lblPassword" runat="server" Text="Password"></asp:Label>
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Height="20px"
style="margin-left: 4px" Width="133px"></asp:TextBox>
<br /><br />
<div class="button">
<asp:label id="lblResult" runat="server" Width="100%"></asp:label>
<asp:Button ID="btnLogin" runat="server" Text="Login" OnClick="btnlogin_Click"
Width="57px" Height="21px"/>
</div>
</div>
</div>
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server"/>
</form>
</body>
</html>
Default aspx and default.cs are both empty like so:
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="head">
</asp:Content>
<asp:Content ID="MainerContent" runat="server" ContentPlaceHolderID="MainContent">
</asp:Content>
As well as logout except for the logout.aspx.cs which contains the logout function:
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeFile="Logout.aspx.cs" Inherits="Logout" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="head">
</asp:Content>
<asp:Content ID="MainerContent" runat="server" ContentPlaceHolderID="MainContent">
</asp:Content>
CS
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using HelloApp;
public partial class Logout : Page
{
protected void Page_Load(object sender, EventArgs e)
{
FormsAuthentication.SignOut();
Response.Redirect("default.aspx");
}
}
Take a look at browser requests in firebug / fiddler / charles to see what's happening to the request for the CSS file.
Try viewing the source of a page on the site and look for the <link ...> tag. What css file does it point to?
I suspect that your Site.css is not in the same folder as your MasterPage/ContentPage.
If your link to the stylesheet is simply Site.css then what ever the folder your MasterPage/ContentPage or just the ContentPage is in will be looking for the stylesheet in that folder.
e.g. if using <link rel="Stylesheet" type="text/css" href="Site.css" />
/Folder1/ContentPage.aspx will be looking for /Folder1/Site.css
If you change your stylesheet to using <link rel="Stylesheet" type="text/css" href="/Site.css" /> Then your website will look for the stylesheet in the root directory. HOWEVER, if your website is running as
`http://localhost:1234/WebsiteFolder/ContentPage'
"WebsiteFolder", then having /Site.css will look for the css file outside of the "WebsiteFolder"
Please post the folder structure of your site, also whether your site is running with a Virtual Path. To find the Virtual Path, view the properties for the website.
use
<link href="~/Site.css" runat="server" id="link1" rel="stylesheet" type="text/css" />
instead of
<link href="Site.css" rel="stylesheet" type="text/css" />
after that css loads properly and works fine....

how to setup masterpage programmatically?

the function
private void SetUpMasterPage(){
this.MasterPageFile = "~/MasterPages/NestedMasterPageTest2.Master";
}
is called on the OnPreInit... This works when the masterpagefile is the base masterpage... But how are we going to make it work for the nested masterpage?
we actually tried
this.Master.MasterPageFile = "~/MasterPages/Base.Master";
but it throws an exception... =(
So, to make things clearer, on the aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Test._Default"%>
<asp:Content ID="testContent" ContentPlaceHolderID="body" runat="server">
This is a test!
</asp:Content>
on the base.Master
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Base.master.cs" Inherits="Test.Base" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>The title</title>
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="body" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
and on the default.aspx.cs
protected override void OnPreInit(EventArgs e){
this.MasterPageFile = "~/MasterPages/Base.Master";
}
it is working...
but when I use a nested master page
<%# Master Language="C#" MasterPageFile="~/MasterPages/Base.Master" AutoEventWireup="true" CodeBehind="NestedMasterPageTest2.master.cs" Inherits="Test.MasterPages.NestedMasterPageTest2" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="body" runat="server">
</asp:Content>
then changed the default.aspx.cs
protected override void OnPreInit(EventArgs e){
this.MasterPageFile ="~/MasterPages/NestedMasterPageTest2.Master";
}
and I changed the default.aspx
<asp:Content ID="testContent" ContentPlaceHolderID="Content2" runat="server">
This is a test which uses a nested master page!
</asp:Content>
it returns an error that says Cannot find ContentPlaceHolder 'Content2' in the master page '/MasterPages/NestedMasterPageTest2.Master', verify content control's ContentPlaceHolderID attribute in the content page. But Content2 is on NestedMasterPageTest2. What really must have happened here?
Your nested master page has Content control but no ContentPlaceHolder control. Try adding it:
<asp:ContentPlaceHolder ID="cplh" runat="server">
</asp:ContentPlaceHolder>
Then, in Default.aspx:
<asp:Content ID="cnt1" ContentPlaceHolderID="cplh" runat="server">
This is a test which uses a nested master page!
</asp:Content>
You need to add an <asp:ContentPlaceholder> tag to your nested master page:
<asp:Content ID="basebody" ContentPlaceHolderID="body" runat="server">
<asp:ContentPlaceHolder ID="Content2" runat="server">
</asp:ContentPlaceHolder>
</asp:Content>

Resources