ASP.NET customized asp:label view state - asp.net

I created a new class for a project. The below is a very slightly simplified version.
public class CustomLabel : Label
{
public string ItemId { get; set; }
protected override void Render(HtmlTextWriter writer)
{
if (!Page.IsPostBack)
LoadText();
base.Render(writer);
}
protected void LoadText()
{
this.Text = "This is a test";
}
}
The problem I'm having is that the Text property is not lasting through postbacks. Even if I manually enable viewstate though the tag on the ascx page. Can the custom label tag not have viewstate? I would hate to have to load the text on every page load unnecessarily.

Move LoadText(); method call to OnPreRender method

Related

ASP .NET Web Forms - Why is custom control's property setter not called by parent using data binding expression?

Why are my custom control's property setters not getting called by the parent page when using data binding expressions to set the control's properties? The setters are called when using a constant to set the control's properties.
MyPage.aspx:
...
<foo:MyControl ID="bar" runat="server" MyProperty="<%# Thirteen %>" />
...
MyPage.aspx.cs:
...
protected int Thirteen { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Thirteen = 13;
DataBind();
}
}
...
MyControl.ascx.cs:
public partial class MyControl : System.Web.UI.UserControl
{
public int MyProperty
{
get => (int)(ViewState["MyProperty"] ?? 0);
set => ViewState["MyProperty"] = value;
}
}
I set a breakpoint on the setter, and it's never called when I load the page.
However, if I change MyPage.aspx from/to this, it works:
<foo:MyControl ID="bar" runat="server" MyProperty="13" />
Is it possible to have the setter called using the data binding expression? What am I doing wrong?
Embarrassing...
My actual code for MyControl.ascx.cs was more appropriately the following:
public partial class MyControl : System.Web.UI.UserControl
{
public int MyProperty
{
get => (int)(ViewState["MyProperty"] ?? 0);
set => ViewState["MyProperty"] = value;
}
// THIS IS THE KEY
protected override void OnDataBinding(EventArgs e)
{
// bunch of stuff, but never calling base.OnDataBinding(e)
}
}
After adding base.OnDataBinding(e); to the overridden method, everything worked as expected.

Custom Control Event not firing inside a user control

I implement a custom control that handle post back event:
namespace CalendarControls
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class CalendarPostback : WebControl, IPostBackEventHandler
{
public delegate void CalendarPostBackHandler(object sender, CalendarPostbackEventArgs e);
public event CalendarPostBackHandler CalendarPostBack;
public CalendarPostback()
{
}
#region IPostBackEventHandler Members
public void RaisePostBackEvent(string eventArgument)
{
string[] values = eventArgument.Split('|');
CalendarPostbackEventArgs args = new CalendarPostbackEventArgs();
args.EventType = (eEventType)Convert.ToInt32(values[0]);
if (args.EventType == eEventType.Insert)
args.EventDate = Convert.ToDateTime(values[1]);
else
args.EventId = Convert.ToInt32(values[1]);
if (CalendarPostBack != null)
CalendarPostBack(this, args);
}
#endregion
}
public class CalendarPostbackEventArgs : EventArgs
{
public CalendarPostbackEventArgs()
{
}
public eEventType EventType
{
get;
set;
}
public DateTime EventDate
{
get;
set;
}
public int? EventId
{
get;
set;
}
}
}
and I use this custom control in a usercontrol ,and call it on a button click inside my usercontrol with following javascript code:
function CallPostBack(eventArguments) {
__doPostBack('<%=ctl1.ClientID %>', eventArguments);
}
and my html code in usercontrol:
<input type="button" value="Insert" onclick="CallPostBack('1|2014/06/12')" />
<CalendarControls:CalendarPostback ID="ctl1" runat="server" ClientIDMode="Static" OnCalendarPostBack="ctl1_CalendarPostBack" />
but when I click on my button, page postback occur but ctl1_CalendarPostBack event not fired. also I must to say that I add user control directly to aspx page (not dynamically) and my aspx page have a master page.
now I have two question:
what's wrong with my code? how to solve this issue?
if I want to add my custom control to an update panel and I want to have an async post back, what I must do?
thank you,
best regards
I found problem! when we use master page ,client id and unique id of control is different and we must to use unique id instead of client id:
function CallPostBack(eventArguments) {
__doPostBack('<%=ctl1.UniqueID %>', eventArguments);
}

ASP.NET is System.Web.UI.Page thread safe

I am wondering if the following code is thread safe?
Can i be be sure that UniqueFoo will indeed be the Unique Foo and will not be override?
public partial class Dummy : System.Web.UI.Page
{
public string UniqueFoo{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var id = int.Parse(Request["Id"]);
UniqueFoo = SomeThreadSafeWCF.GetUniqueFoo(id);
}
}
what about the following (static)
public partial class Dummy : System.Web.UI.Page
{
public static string UniqueFoo{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var id = int.Parse(Request["Id"]);
UniqueFoo = SomeThreadSafeWCF.GetUniqueFoo(id);
}
}
i later want to use UniqueFoo in a [WebMethod]
[WebMethod]
public static void SetSomeObject(SetSomeObject obj)
{
SomeThreadSafeWCF service = new SomeThreadSafeWCF ();
service.SetSomeObject(UniqueFoo, obj);
}
EDIT:
I am getting SetSomeObject from JS and UniqueFoo is coming from ASP.NET
will i have any issues when NOT using the static in my Dummy class according to your answers?
Surely your first sample is thread safe because when a request of a page post to the Web Server asp.net make new instance of your page and call page_load so if your SomeThreadSafeWCF.GetUniqueFoo() always make a unique Foo everything is thread save
Your second code snippet is not thread safe because you are modifying the value of a static field. So for example if later in this page you attempt to read the value of this UniqueFoo field you might not get the value you expect.
The first code snippet is fine because the field is not static.
If you want to use the UniqueFoo in a WebMethod then I would recommend you to pass it to this web method when calling it.
[WebMethod]
public static void SetSomeObject(SetSomeObject obj, string uniqueFoo)
{
SomeThreadSafeWCF service = new SomeThreadSafeWCF ();
service.SetSomeObject(uniqueFoo, obj);
}

AutoPostBack Interface

I'm creating a set of Web User Controls which will share a common base class. The base will always contain a WebControl (either a Textbox, DropDownList, CheckBoxList, RadioButtonList, ListBox, and maybe others) and a RequiredFieldValidator. All is well, except that my abstract InputControl property (defined as type WebControl) doesn't seem to have the AutoPostBack property which I want them all to have (I assume this is because not all WebControls support AutoPostBack). I would love to put this functionality in completely in the base class and not have to define it in each child. It would look like:
public abstract WebControl InputControl { get; set; }
public bool AutoPostBack {
get { return InputControl.AutoPostBack; }
set { InputControl.AutoPostBack = value; }
}
But this obviously won't work because AutoPostBack is not a property of WebControl. Is there another interface that I could specify that would support this, or do I need to create my own?
autopostback is not in any base class because only some controls need autopostback property. what you can do is to use generics
public class MyBaseUC<T> : System.Web.UI.UserControl
{
public abstract T InputControl { get; set; }
}
public partial class WebUserControl1 : MyBaseUC<TextBox>
{
protected void Page_Load(object sender, EventArgs e)
{
InputControl.AutoPostBack = false;
}
}
Regards.

ASP.NET ITemplate with TemplateInstance.Multiple

I can't seem to find any examples on how to implement ITemplates with multiple instances. All I need to do is build out a navigation that has a template for the content of each navigation item.
If your control is not a databound control, you can solve the problem by something as follows. But, I haven't tested it.
public class FooItem : WebControl, INamingContainer
{
protected override CreateChildControls()
{
Control placeHolder = this.FindControl(((Foo)this.Parent).ItemPlaceHolderId);
if (placeHolder != null)
{
// Add some controls to the placeHolder.
}
}
}
public class Foo : WebControl, INamingContainer
{
public ITemplate ItemTemplate { get; set; }
public string ItemPlaceHolderId
{
get { ... }
set { ... }
}
public FooItemCollection Items
{
get { ... }
}
protected override CreateChildControls()
{
foreach (FooItem item in this.Items)
{
this.ItemTemplate.InstantiateIn(item);
}
}
}
Look at documentation of creating a data-bound templated control.
Unfortunately, the best documentation I've found is from .NET 1.1:
Developing a Templated Data-Bound Control.
Note from MSDN:
This TemplateInstanceAttribute class
is optional. If a template property is
not extended with a
TemplateInstanceAttribute class, the
default value, the Multiple field, is
used.
So any ITemplate example that does not use the TemplateInstanceAttribute is using TemplateInstance.Multiple.

Resources