NullReferenceException in usercontrol from class library, but not from web project - asp.net

I have following project structure where web application may contain user controls from the same web project or from a separate class library. The issue is in Default.aspx.cs, when I execute usercontrol2.SetValues(); I receive NullReferenceException since for some reason textbox2 is null. I've tried using EnsureChildControls(); but it does not help either. Should I register or invoke these usercontrols in some other way? Why does not it work out-of-box?
User control in web project
WebUserControl1.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<asp:TextBox runat="server" ID="textbox1"></asp:TextBox>
WebUserControl1.ascx.cs
namespace WebApplication1
{
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public void SetValues()
{
textbox1.Text = "Hello";
}
}
}
User control in class library
WebUserControl2.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl2.ascx.cs" Inherits="ClassLibrary1.WebUserControl2" %>
<asp:TextBox runat="server" ID="textbox2"></asp:TextBox>
WebUserControl2.ascx.cs
namespace ClassLibrary1
{
public partial class WebUserControl2 : System.Web.UI.UserControl
{
public void SetValues()
{
textbox2.Text = "world";
}
}
}
Main page
Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%# Register tagPrefix="web" tagName="WebUserControl1" src="WebUserControl1.ascx" %>
<%# Register TagPrefix="web" Namespace="ClassLibrary1" Assembly="ClassLibrary1" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<web:WebUserControl1 runat="server" ID="usercontrol1"></web:WebUserControl1>
<web:WebUserControl2 runat="server" ID="usercontrol2"></web:WebUserControl2>
</asp:Content>
Default.aspx.cs
using System;
using System.Web.UI;
namespace WebApplication1
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
usercontrol1.SetValues(); // OK
usercontrol2.SetValues(); // NullReferenceException
}
}
}

Using ascx usercontrols from a different assembly is not possible.
I think you should look at this problem this way. Your classlibrary is compiled into a dll-file. This is the only thing that is available for your webapplication. The ‘ascx’ doesn’t get compiled into the dll, and is not available.
If you really want to keep some controls separated from your web-project, I think there are a few options:
Convert your usercontrol to a customcontrol. Custom controls are a bit more difficult to create, but it is certainly not impossible. This way you really get a re-usable control.
See also this question; it addresses your problem and there’s also a link to an algorithm which ‘converts’ an ascx usercontrol to a custom control. (I didn’t test that)
Asp.NET user control referenced from another project/dll has NULL properties
Make sure your ascx files are available to the web-project, by publishing to a path in your output. Then use LoadControl to load them serverside. This could work, but I also think some of the reusability from your classlibrary is lost.

Related

Accessing Properties of the code-behind from aspx page in web application project

I have a property x in my code-behind file in a web application project. It gives me compile time error while it does not give any error in website project
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="test.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= x2 %>
<%# x2 %>
</div>
</form>
</body>
</html>
Codebehind file :
using System;
namespace test
{public partial class WebForm1 : System.Web.UI.Page
{
public int x2 = 2;
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
It is working fine when I use the same technique in my website project
Kindly help
Thanks
Check if there are any other errors in your code behind WebForm1.aspx.cs.
like missing reference or any other compile error.
This works for me. Are you sure there's a value in ViewState? On form load add a value to test.
ViewState["FormMode"] = "ViewApplicant";
lblMessage.DataBind();
Also make sure the label has some text to view. It could be showing but is empty.
<asp:Label ID="lblMessage" runat="server"
Text="some text"
Visible='<%# FormMode == "View" || FormMode == "ViewApplicant" %>'>
</asp:Label>
Your code is perfectly okay. While accessing the variable/property initillay, the red underline may appear under the expression indicating the compile error, but when you build the solution, there should be no error.
Your original post has changed so here's a new answer.
Try removing the namespace from the code behind and change 'inherits' on the page to Inherits="WebForm1".
page directive:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="WebForm1" %>
code behind:
using System;
public partial class WebForm1 : System.Web.UI.Page
{
public int x2 = 2;
protected void Page_Load(object sender, EventArgs e)
{
}
}
'Inherits' must match the partial class name.

How to create multiple code behind file for .aspx page

I have a situation where I need to create multiple code behind files for a single .aspx page in c# asp.net. Actually I have a web form on that huge coding is done and I need multiple developer's working on it simultaneously. How can I achieve the same?
Here is the code snippet I tried
Class 1 MyPartialClass.cs
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void PrintText(string pt)
{
Response.Write(pt);
//lblTest.Text = pt; //Can not access this label in partial class.
}
}
}
Class 2 which is Default.aspx.cs
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PrintText("Hello World");
}
}
}
and my HTML source
<%# Page Language="C#" AutoEventWireup="false" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblTest" runat="server"></asp:Label>
</div>
</form>
</body>
</html>
ASP.NET will always generate your code behind files as partial classes
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
You can therefor separate the code behind in different files, if you pertain the definition as partial and keep the class under the same namespace.
Edit : The Web Project
//Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:Label ID="lblTest" runat="server" Text="Label"></asp:Label>
</asp:Content>
//Default.aspx.cs
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PrintText("Hello World");
}
}
}
//MyPartialClass.cs
namespace WebApplication1
{
public partial class Default
{
protected void PrintText(string pt)
{
Response.Write(pt);
lblTest.Text = pt; //lblTest is accessible here
}
}
}
I haven't modified any other generated files. One thing I like to mention is that the Default.aspx.cs file that has been generated was generated with the class name "_Default". I have changed it to Default and Visual Studio refactored the change across all files that contain a definition for that class, except the Default.aspx file, where I had to manually modifiy from Inherits="WebApplication1._Default" to Inherits="WebApplication1.Default".
Edit 2:
I kept searching the internet, and according to http://codeverge.com/asp.net.web-forms/partial-classes-for-code-behind/371053, what you are trying to do is impossible. Same idea is detailed at http://codeverge.com/asp.net.web-forms/using-partial-classes-to-have-multiple-code/377575
If possible, consider converting from Web Site to Web Application, which supports what you are trying to achieve. Here is a walkthrough on how to perform this conversion: http://msdn.microsoft.com/en-us/library/vstudio/aa983476(v=vs.100).aspx
You need to set up a source safe server in order to that, like Team Foundation Server.
You can easily just add partial classes to your code.
http://www.codeproject.com/Articles/709273/Partial-Classes-in-Csharp-With-Real-Example

How to avoid build errors with aspx include files?

I have an aspx file that will contain a lot of sections and I would prefer to have each section in its own include file. I'm okay to put all of the code behind into the main file. I'm using: <!-- #include file ="section1.aspx" --> in the body. When I build (I'm still only including the first section with code), I get "The name 'lbl_phone' does not exist in the current context" because the code behind has a routine that references this screen field which IS in the include file. What is a better way to go about this?
Edit (as it is now, hope I cut it down properly here, builds good now but error in browser):
file ola.aspx
<%# Page Language="C#" AutoEventWireup="true" Inherits="_ola" Codebehind="ola.aspx.cs" %>
<%# Register TagPrefix="section" TagName="account" Src="account.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><body><form id="ola_form1" runat="server">
<section:account id="section_account" runat="server" />
</form></body></html>
file: ola.aspx.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 System.Text.RegularExpressions;
using System.Data.SqlClient;
public partial class _ola : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
lbl_phone.Text = "000-000-1234";
}
}
file: account.ascx
<%# Control Language="C#" ClassName="_ola" CodeBehind="account.ascx.cs" %>
Call us at <asp:Label ID="lbl_phone" runat="server" Text="lbl_phone"></asp:Label>
At runtime in the browser, I get: Object reference not set to an instance of an object. (for the line with lbl_phone.Text = ...)
Don't use server side includes. They don't work well in the ASP.NET architecture.
Instead, embed reusable stuff into .ASCX user controls. MSDN How To article.
ASCX File MyControl.ascx
<% # Control Language="C#" ClassName="Spinner" %>
<table>
<tr><th>Column 1</th><th>Column 2</th></tr>
<tr><td>Some content</td><td>Some more content</td></tr>
</table>
Then this can be embedded on as many ASPX pages as you like.
<%# Register TagPrefix="uc" TagName="MyControlName" Src="~\Controls\MyControl.ascx" %>
<uc:MyControlName ID="MyControl1" runat="server" />
Edit- You should make these ASCX files as portable as possible in your application so that they're self contained units. There shouldn't be much of a need for your ASPX code behind to reference a control contained in the ASCX file. You can do code behinds for user controls (MyControl.ascx.cs or MyControl.ascx.vb) if necessary, or you can use a script block to embed the code directly in the ASCX page.
.NET Framework will not follow server side includes and so it won't compile properly if you try to reference a control that is being included via SSI. But you could potentially reference a control in an ASCX file. For example...
MyAdvancedControl.ascx
<% # Control Language="C#" ClassName="Spinner" %>
<asp:Label runat="server" id="lbl_phone" />
<script runat="server">
public Label Lbl_phone {get {return lbl_phone;}}
</script>
MyPage.aspx
<%# Register TagPrefix="uc" TagName="MyAdvancedControlName" Src="~\Controls\MyAdvancedControl.ascx" %>
<uc:MyAdvancedControlName ID="MyControl2" runat="server" />
MyPage.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
MyControl2.Lbl_phone.Text="Galaxy S4";
}
Controls defined as part of a Page or Master Page or User Control are private by default. To get around that, add a public property that exposes it. Put this property in account.ascx.cs
public Label lbl_phone_public_version{
get {
return lbl_phone;
}
}
When you try to reference lbl_phone from code on ola.aspxcs, you have to do it through the parent control, like this:
protected void Page_Load(object sender, EventArgs e)
{
section_account.lbl_phone_public_version.Text = "000-000-1234";
}

My web control doesn't appear in my web page in a different folder

My web control doesn't appear in my web page in a different folder,
However it works in another web page in the same location.
My source code is like this :
..
<%Register src="~/UI/Human/HumanUserControl.wuc" TagPrefix="uc1"
TagName="HumanUserControl"/>
...
<uc1:HumanUserControl runat="Server" id="HumanUserControl"/>
...
Error:
Request is not available in this context
The syntax on your Register tag is incorrect. And I'm not sure why you're using a ".wuc" extension instead of the default ".ascx".
You need matching <% %> tags, like so:
<%# Register Src="~/UI/Human/HumanUserControl.wuc" TagPrefix="uc1" TagName="HumanUserControl" %>
If you delete the <%Register .../> and <uc1 .../> tags from your page completely, then in Visual Studio, drag-and-drop the user control from the Solution Explorer directly onto your page wherever you want the control to appear, it will automatically add the correct Register and user control tags for you.
If this doesn't clear things up, then provide more detailed error information, including the code where the exception is thrown.
The following works just fine:
~/UI/Human/HumanUserControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="HumanUserControl.ascx.cs" Inherits="UserControlTest.UI.Human.HumanUserControl" %>
<asp:Label ID="lblTest" runat="server" />
~/UI/Human/HumanUserControl.ascx.cs
namespace UserControlTest.UI.Human
{
public partial class HumanUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
lblTest.Text = Request.Browser.Browser;
}
}
}
~/Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="UserControlTest._Default" %>
<%# Register Src="~/UI/Human/HumanUserControl.ascx" TagPrefix="uc1" TagName="HumanUserControl" %>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<uc1:HumanUserControl runat="server" id="HumanUserControl" />
</asp:Content>

Rendering template for newform and code behind

I'm trying to create a rendering template for my forms which need complex validations treatments.
the rendering template is working fine wwith :
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>ListForm</Display>
<Edit>ChaisTemplate</Edit>
<New>ChaisTemplate</New>
</FormTemplates>
</XmlDocument>
</XmlDocuments>
and with my ascx :
<%# Control AutoEventWireup="true" CodeBehind="ChaisTemplate.ascx.cs"
Inherits="TransactionsFormsTemplates.ControlTemplates.ChaisTemplate, TransactionsFormsTemplates"
Language="C#" %>
<%# Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Namespace="Microsoft.SharePoint.WebControls" %>
<%# Register TagPrefix="wssuc" TagName="ToolBar" Src="~/_controltemplates/ToolBar.ascx" %>
<%PageLoad(this, null);%>
<SharePoint:RenderingTemplate ID="ChaisTemplate" runat="server">
.....
but I can't have any control mappings in my code behind (in the webapp bin with cas policies, and it's correctly deployed)
this :
<asp:TextBox runat="server" ID="test"></asp:TextBox>
is null when it comes to :
public partial class ChaisTemplate : System.Web.UI.UserControl
{
protected TextBox test;
so everytime I call test.Text on functions, I get a nullreferenceexception, because test is never mapped to my ascx textbox. why ?
plus, the PageLoad is never called like in classic asp.net pages, even with <%PageLoad(this, null);%> at the beginning.
however every event works :
<asp:Button runat="server" ID="button" OnClick="button_OnClick"/>
this will actually call button_OnClick in my code behind. But all my properties are null because not mapped.
did I miss something?
I'v been doing it like this. Take this as an example RenderingTemplate:
<SharePoint:RenderingTemplate ID="ParentItemsListView" runat="server">
<Template>
<table cellpadding=0 cellspacing=0>
<tr><td nowrap class="UserGenericHeader"><asp:Label ID="lblParentItems" runat="server" /></td></tr>
<tr><td><SharePoint:ListViewByQuery ID="listViewByQuery" runat="server" /><br /></td></tr>
</table>
</Template>
</SharePoint:RenderingTemplate>
Then in Render event i can reference these controls like this:
[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
protected override void Render(HtmlTextWriter output)
{
if (this.Visible)
{
Label lblParentItems = this.TemplateContainer.FindControlRecursive<Label>("lblParentItems");
lblParentItems.Text = "Pievienotie " + this.ChildList.Title;
ListViewByQuery listView = TemplateContainer.FindControlRecursive<ListViewByQuery>("listViewByQuery");
listView.List = this.ChildList;
...
base.Render(output);
}
}
Ahh, yes, i use a handy extension function
public static T FindControlRecursive<T>(this Control parentControl, string id) where T : Control
{
T ctrl = default(T);
if ((parentControl is T) && (parentControl.ID == id))
return (T)parentControl;
foreach (Control c in parentControl.Controls)
{
ctrl = c.FindControlRecursive<T>(id);
if (ctrl != null)
break;
}
return ctrl;
}
However i had an issue where i inherited from SaveButton that i couldn't reference a control. In that case i changed so that i inherit from FormControl and i could find my control under this.Controls.
Also note that you cannot reference controls up until OnLoad event has executed (i.e if you're in OnLoad function, call base.OnLoad(e) before referencing controls.
Why is it so? I guess because it's not like you are having a template and then code behind (working with the same class/object), but it's more like you are rendering that ascx template in a different class/object file.

Resources