Dynamically Load a user control (ascx) in a asp.net website - asp.net

I am trying to dynamically load a user control in an asp.web site. However due to how asp.net websites projects are setup (I think), I am not able to access reach the type definition of the user control.
I get a message saying that my class HE_ContentTop_WebControl1 is: he type or namespace name 'HE_ContentTop_WebControl1' could not be found (are you missing a using directive or an assembly reference?)
Any idea how this could be made to work ? I have attempted using namespace but it seems to me that asp.net websites are not designed to work with namespaces by default. I would be interested in a non namespace approach.
TIA
public partial class HE_Default :
System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e)
{
var control = (HE_ContentTop_WebControl1)Page.LoadControl("~/ContentTop/WebControl1.ascx");
}
}

Assuming the control exists in the same assembly as your web project, you need to add a reference directive in your .aspx file,
e.g:
<%# Reference Control="~/Controls/WebControl1.ascx">
Keep in mind it often takes a few minutes (or sometimes a build) for IntelliSense to pick this up.

It can easily be done using namespaces. Here's an example:
WebControl1.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="WebControl1.ascx.cs" Inherits="MyUserControls.WebControl1" %>
Notice that Inherits references the namespace (MyUserControls), and not just the class name (WebControl1)
WebControl1.ascx.cs:
namespace MyUserControls
{
public partial class WebControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
Notice that the class have been included in the namespace MyUserControls
Default.aspx.cs:
using MyUserControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var control = (WebControl1) Page.LoadControl("~/WebControl1.ascx");
}
}
This approach potentially allow you to redistribute your user controls (or keep them in a separate project) without the hassle of referencing them in your .aspx files.

Namespaces are not supported under the website model. As such, I could not get any of the solutions proposed to work. However, there is a solution. Create an interface and place it into app code and then implement the interface in the user control. You can cast to the interface and it works.

The subject of this post is a bit misleading. If you just want to add a control dynamically, you will not have to reference the control and therefore you can just add it with something simple like:
protected void Page_Load(object sender, EventArgs e)
{
Page.Controls.Add(Page.LoadControl("~/MyControl.ascx"));
}
without any namespace hassel.

the reference is not enough using
<%# Reference Control="~/Controls/WebControl1.ascx">
in the aspx file is just one part of the answer.
you need also to add the calssName in the User Control aspx file
<%# Control ClassName="WebControl1" Language="C#" AutoEventWireup="true" CodeFile="WebControl1.ascx.cs" Inherits="AnySpaceName.DateSelector" %>
and then you can use the userontrol in your aspx file
AnySpaceName.WebControl1 WC = (AnySpaceName.WebControl1)Page.LoadControl("~/WebControl1.ascx");

Casting the user control this way may create many problems .my approach is to create a class (say control Class) put all the properties and method you need for casting in it and inherit this class from System.Web.UI.UserControl .Then in your user cotrol code file instead of System.Web.UI.UserControl user this control class .
now when ever you need casting, cast with this class only . it will be light casting as well.

Related

extending ASP.NET Page using MasterPage attributes as properties

I have an authentication roles-based system: different roles are redirected to different folders and in each folder there is a web.config that allows the access only to a particular username.
Few roles have the default page in common with a gridview that react in different ways depending on the role(different columns are shown, events trigger different methods, etc.).
so my problem is that everytime I need to make minor changes to a page I need to copy/paste the same changes to all the others default pages in the other folders.
In terms of code I solved by creating a DefaultFather class which extends System.Web.UI.Page and every other Default class inherits from DefaultFather. In this way, if I dont declare a Page-life-method, the DefaultFather method will be triggered.
but what about the graphic part(html, javascript, asp components, etc...)??
I created a NestedMasterPage just for the Default pages but everytime I need to change the appearance/behaviour of controls(gridview, buttons, linkbuttons) I must use the FindControl() method.
there isnt really another way to solve this problem?
Im thinking of using the Page_Load() method to search for each control with FindControl() and save them into attributes for later usage but it doesnt really look like a good solution.
It would be nice if I could use the masterpage components as properties but I think that in order to do that I should create public properties and I dont know if it will cause some kind of security problem.
any suggestion?
btw, if masterpage is the solution, should I remove the DefaultFather class and place the code directly into the masterpage? or is it a good idea to have another class just for the code?
I'd say there's nothing wrong with having both a master page and a base class for your page. They serve different purposes. The master page is generally all about layout, and the base class would be about page functionality.
If you want to manipulate the markup on your master page, rather than accessing the fields directly, I'd say create a logical function which does what you need it to do, and let the master page do it.
// Site.Master.cs
public void HideSubmitButton()
{
btnSubmit.Visible = false;
}
// Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
((SiteMaster)Master).HideSubmitButton();
}
I'd probably wrap that cast so you can use it more easily - that is something that would belong in your base class:
// DefaultFather.cs
protected new SiteMaster Master { get { return (SiteMaster)base.Master; } }
// Default.aspx.cs
Master.HideSubmitButton();
EDIT
Per your comment about attaching event handlers - if you need to attach events to objects that live on the master (which may not be a good idea - ideally the event handler for something living on the master lives on the master - but if you really need it) you can expose methods to do that as well, like:
// Site.Master.cs
public void AttachEventHandlerToGoButton(EventHandler eventHandler)
{
btnGo.Click += eventHandler;
}
// Default.aspx.cs
Master.AttachEventHandlerToGoButton(DoMyThing);
private void DoMyThing(object sender, EventArgs e) { }
or if you want to get fancy, write a wrapper event:
// Site.Master
<asp:Button ID="btnGo" runat="server" OnClick="btnGo_Click" />
// Site.Master.cs
public event EventHandler GoButtonClick;
protected void btnGo_Click(object sender, EventArgs e) {
if (GoButtonClick != null) {
GoButtonClick(sender, e);
}
}
// Default.aspx.cs
Master.GoButtonClick += DoMyThing;
private void DoMyThing(object sender, EventArgs e) { }
Also see my edit on the Master wrapper - you need the base. there to avoid a stack overflow.

ASP.Net Calling Site.Master method from web page not working

I saw on several web pages how to interface to a public method defined in a master file from a web page call behind code that uses that master file.
(I am using ASP.Net 4.0 on Visual Studio 2012.)
The procedure is (copied from article):
Make sure the function is accessible to the page (i.e. declared
public), and use the MasterType declaration in the ContentPage:
<%# Page .... %>
<%# MasterType VirtualPath="~/masterpage.master" %>
In the page, use Page.Master.MyFunction() to access the function.
*Note: before being able to access the function, you'll need to save & build.
The problem is that I do not see the method. Here is what I have:
Web Page (stored in /MyFolder, so /MyFolder):
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Logout.aspx.cs" Inherits="BvCorpMain.Candidates.Logout" %>
<%# MasterType VirtualPath="/SiteMasters/Site.Master" %>
Site.Master CS file (stored in /SiteMasters folder):
public void UpdateUserBlocksToCookie()
{
}
When I go into the code behind for the logout page and in a method I type in "Page.Master.", I do not see my method.
Your page is inheriting from System.Web.UI.Page, which only knows that its master page is of type System.Web.UI.MasterPage. If you are making modifications to a child class of MasterPage, then you need to cast the Page.Master property to your child class.
public class MyPage : System.Web.UI.Page
{
public new MyMaster Master { get { return base.Master as MyMaster; } }
public void Page_Load(object sender, EventArgs e)
{
Master.MyMasterPageFunction();
}
}
public class MyMaster : System.Web.UI.MasterPage
{
public void MyMasterPageFunction()
{
}
}
The previous answer did educate me, however I believe the resolution was to restart VS2012, maybe cleaning the solution and rebuilding did not hurt. Either way.
Microsoft adds in the following code automatically to the .aspx.designer.cs file.
/// <summary>
/// Master property.
/// </summary>
/// <remarks>
/// Auto-generated property.
/// </remarks>
public new MyNamespace.Site Master {
get {
return ((BvCorpMain.Site)(base.Master));
}
The previous answer conflicts with this definition. Also, the previous answer of MyMaster, although granting access does not give (automatically at least) to needed form information. I checked. Using the existing master file is the cleanest.
The definition for the master.cs file is:
namespace MyNamespace
{
public partial class Site : System.Web.UI.MasterPage
As you can see, Microsoft did give access to MyNamespace.Site, which is what I needed, with "Master.".
I did not think to check the .aspx.designer.cs file for that definition, when I was having the problems. Possibly the definition was lacking and got added later, when either I rebuilt or did a save, which I had previously done, or whatever.
Knowing the addition does simplify things, as I can add that in manually if it does not exist using that construct.

Is SqlDataSource can be shared across different aspx page?

as the title said is SqlDataSource can be shared across different aspx page?
i have exact same sqldatasource on multiple aspx page, is it possible to create one and shared for all the pages.
thanks
Sure. If you really mean shared, as in all pages use the same SqlDataSource, create a Master Page and put the data source in the master. In the codebehind, expose it as a property of the master. From there, you can reference it from any page that uses the Master.
Second option - create a base Page class:
public class MyPage : Page
{
private SqlDataSource mDataSource;
public override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// some code to init your data source - depending on your
// implementation, this may need to be in OnInit instead
}
public SqlDataSource DataSource
{
get { return mDataSource; }
}
}
In this case, any time you create a new page, go to the code behind and change the declaration from implementing Page to MyPage. All pages that implement MyPage will have an SqlDataSource member, though each would have its own instance, so that's not really "sharing" the same SqlDataSource.
Either option gets you where you want to go I think.
UPDATE: Poster requested an example of exposing in as a property of the master:
Given a Master Page with the following:
<asp:SqlDataSource runat="server" ID="mDataSource" ... the rest of your properties .... />
<asp:ContentPlaceHolder runat="server" ID="MainContent"/>
In the code-behind for the master, define the property:
public class SiteMaster : System.Web.UI.MasterPage
{
public SqlDataSource MasterDataSource
{
get { return mDataSource; }
}
// the rest of your master page's codebehind
}
In the pages you define for using your master page, add the following below the #Page declaration:
<%# MasterPage VirtualPath="~/site.master"%>
Now, in the codebehind for that page, you can reference:
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource ds = this.Master.MasterDataSource;
}
As long as you have as long as you have a <%# MasterType VirtualPath="~/ PATH TO YOUR MASTER" %> in your aspx page, you can reference any properties you expose in the master.
Happy coding.
B
Controls are specific to pages. To share it across pages put it in a UserControl and then expose it through the public property of the UserControl.
If you mean the connection string, the answer is yes. You can put it in a public shared class.
If you mean the connection being open during several pages. No.
You should always close the connection ASAP to avoid memory leaks.

Type '_Default' already defines a member called 'Page_Load' with the same parameter types

I've been renaming some classes and packages in my aspx project and now i have this error:
"Type '_Default' already defines a member called 'Page_Load' with the
same parameter types"
I have two aspx pages. In the default.aspx codebehind i see:
Default.aspx:
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="_Default" %>
Default.aspx.cs:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
//error line under 'Page_Load'
}
search.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="search.aspx.cs" Inherits="_Default" %>
search.aspx.cs:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
}
Every new ASPX page I add to my project is automaticly added to some namespace.
I've tried changing the inherits attribuut. But i couldn't find a way to fix this error and to get rid of the namespace.
I'm using Visual Studio 2010.
Every page you add is automatically configured to namespace depending on your folder structure. I don't see enough code and structure, but are you sure, that you don't have the Page_Load defined twice? At least the error message says so. Does it behave same even when you use different class name than _Default ?
After edits:
Yea, there we go. You define same class (_Default) in both Default.aspx and Search.aspx ... You should rename your classes according to conventions. ie: use class "Default" in your Default.aspx and use class "Search" in your Search.aspx
Double click the error, temporarily rename the Page_Load to something else. Go down into the body of the function and type Page_Load. Press F12. That will get you to the place where you have second Page_Load method already defined. You'll probably see that it's in another partial _Default class in the same namespace.
Just to add up a specific case.
You can come across to this situation when you convert Web Site into Web Application.
When your project in form of Web Site, when you add for example Default.aspx into two different folders they both created without namespace with the same class name. Both declared partial and it is just fine. But when you convert into Web Application and try to build they start conflicting as they are in the same namespace, declared partial and have their own Page_Load methods.
One of the solutions can be giving distinct class names or encapsulating into different namespaces in accordance with the folder structure.
Since your class is public partial class _Default it's probably some naming that is causing the problem. Try to identify the other part(s) of _Default. Since it's a partial class you're able to have as many partials as you want.. Problem is probably that Page_Load is defined in one of those.
Below follows issues I have encountered when copying files into my solution, clicking on the reported error or on "Go to Definition" mislead me to spot the cause. The hint is one line above..... !
I'm exposing the Problem AND how I finally Resolved it.
Errors when building the application:
Error 1 Type 'Solution1.Web.yourABC' already defines a member
called 'Page_Load' with the same parameter types
C:\\trunk\Solution1.Web\yourABC.aspx.cs 12 24
Solution1.Web
Error 2 Type 'Solution1.Web.yourABC' already defines a member
called 'Page_Load' with the same parameter types
C:\\trunk\Solution1.Web\GuideABT.aspx.cs 12 24
Solution1.Web
How the problem arose:
I copy/pasted a file .aspx in the same solution to make a new file.
C#: Error like below started to appear; worst other misleading errors started to impact the application at runtime:
* Be aware that error 1 IS NOT an error it is CORRECT, as it is the source code
Error 1 Type 'Solution1.Web.yourABC' already defines a member called 'Page_Load' with the same parameter types C:\<folderpath>\trunk\Solution1.Web\yourABC.aspx.cs 12 24 Solution1.Web
Error 2 Type 'Solution1.Web.yourABC' already defines a member called 'Page_Load' with the same parameter types C:\<folderpath>\trunk\Solution1.Web\GuideABT.aspx.cs 12 24 Solution1.Web
Both classes "Page_Load" are empty, normally they are generated automatically by the Visual Studio Engine
Solution:
Change the .cs file of the newly create/pasted aspx page to reflect the page name after the Class "name". In this case "GuideABT.aspx" is the new pasted & renamed aspx file:
Correction on Error 1: NO CORRECTION NEEDED as it is the copied from file. MAKE SURE THAT the name of the file and the name of the class reference ARE the same in the .cs files:
File name yourABC.aspx, check the .cs extension files:
namespace Solution1.Web
{
public partial class yourABC : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
Correction on Error 2: MODIFY the pasted file. Correct the CLASS NAME to reflect the name of the .aspx file.
File name GuideABT.aspx, check the .cs extension files:
ORIGINAL code in .cs
namespace Solution1.Web
{
public partial class *yourABC* : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
CORRECTED this code in .cs TO
namespace Solution1.Web
{
public partial class **GuideABT** : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
Issue RESOLVED.
Cheers.

How do you access the content of a ASP.NET control?

I was wondering if it is possible to do something like this:
<uc1:TestControl ID="TestControl1" runat="server">
<div>More random HTML, etc...</div>
</uc1:TestControl>
I got an error of "Type 'System.Web.UI.UserControl' does not have a public property named 'div'.". Doing a little research, I found I could add the following property to the server control:
[ParseChildren(false)]
public partial class TestControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
Is it possible to read the content from an ASP.NET control?
Edit: Changed wording to reflect that I am curious if you can do this with either a server or user control
In a server control, you would create a property that implements ITemplate to contain that content. I'm not positive whether that is possible in a user control, but it may be.
yeah it is possible
check this MSDN Article about creating templated user controls, plus you can add [ParseChildren(false)] to the user control class so you can see them from the page holding them.
http://msdn.microsoft.com/en-us/library/36574bf6.aspx
hope this helps.

Resources