ASP.Net Server Control - Setting Properties From Database/External Source - asp.net

My current issue is that I've created a server control, but want to set the properties of the control class (which are temporarily being defined as custom expando attribs for jQuery access via AddAttributesToRender()/AddAttribute()) from a database/external source. Since there's no "code-behind" for this control, was looking for suggestions on how to approach this.
I guess I could always code the data access in the control's PreRender, then apply the values to my custom attribs in AddAttributesToRender() or create dynamic JavaScript to attach an object containing the values. I was really interested in sort of "wrapping" the server control in an object and sorta "instantiate" the child server control, setting its properties via reference (which would hopefully fall out as my custom attribs).
I'm prob not making sense... I guess to simplify, I want to have a parent wrapper or external custom class in which to factor out/encapsulate the data access (maybe hook up to Entity Framework) needed to grab the control's prop vals from the db (or config file), and be able to set the control props (attribs) from there/externally/as a parent to the control before the control rendering fcns (are called by ASP. Not even sure how that would work.
Thx for your assistance!

Related

ASP.NET long Name attribute - Why is there no ClientNameMode

In ASP.NET much has been made about the ClientIdMode property that gives developers greater control over the a control's ID attribute as it appears in the HTML.
However little attention appears to have be paid to the way the controls render their Name attribute. It appears to be a simple concatenation of the control's ID and its hierarchy of naming containers.
Given a sufficiently complex web page these names get very long. They not only make the HTML payload big (and ugly) but are also posted back to the server on every postback. (Also, they make their way into the Control State of some third party control suites. )
Why isn't there a ClientNameMode property - or similar? Surely it is as important as the Id attribute? Is it possible to override some method that generates / rehydrates the Name attribute so that we can man handle it to maybe match the Id? (made shorter by the ClientIdMode)
An example of a name of a control on a page that I am working on is
USoWAR1_tabContainer_UDetailsTabContainer_tabContainer_UDetailsTab_UDetails1_UDueDateAndNotifications1_decDetail_DataEntryRow1_datDueDate_DateTimePicker_calendar_AD
As far as I know the only way to alter this functionality is to extend controls into your own and override UniqueID property (e.g. by returning Server-side ID).
I had this same issue, and had to use JS to set the attr after loading.
$('#idofdomobjiwanttoname').attr("name", "whatIWantToNameIt");

How is the 'name' attribute calculated in ASP.NET?

Im trying to understand how the 'name' attribute works for elements in markup rendered via ASP.NET
I.e. <select id="lblxyz" name="ctl00$c$ctl341$lblxyz">
What are ctl00, c and ctl1341?
If I create a WebControl, give it an arbitrary id, then place a Button inside its Controls collection, the name attribute does not seem to reflect the container's id?
The key thing as you have discovered is that not all controls trigger this behaviour. The key is the INamingContainer interface. Only Naming Containers will contribute to the name of the control as you have seen, other controls won't.
The MSDN page linked above says it pretty well: that interface "identifies a container control that creates a new ID namespace within a Page object's control hierarchy."
The generated name attribute typically always starts with ctl00, and the rest is generated based on where the control lives in the control hierarchy. Any parent controls implementing the INamingContainer interface will contribute to the names generated for any child controls.
This may be of interest to you, it outlines out the id/names are generated: http://www.mostlylucid.net/archive/2008/11/03/way-too-much-information-on-control-ids-and-asp.net-4.0.aspx
You can control how the client ID appears using the new ClientIDMode:
All about Client ID Mode in ASP.NET 4

Is it possible to have classic asp.net dynamically load subtypes of declared webcontrols

I want to be able to declaratively specify the webcontrols of any given page in the standard way, but have the runtime not necessarily new up instances of the types I specified, but rather for instance check against web.config whether a different webcontrol (which would inherit from the specified one) should be used instead.
for instance I could have a webcontrol in the path /templates/controls/default/PersonSelector.ascx and another one in the path /templates/controls/CUSTOMER_A/PersonSelector.ascx (inheriting from the first)
so if my config indicated that I preferred to load controls from the CUSTOMER_A folder where available, and since it would be available in this case, the actual markup which was used for the page would come from .../CUSTOMER_A/PersonSelector.ascx. All code which compile-time assumed that it was in fact an instance of ../default/PersonSelector.ascx would still work since it is actually a subclass.
This would afaik be a major benefit to our site which is a multitenant site in which 99.5% of the generated html is identical across all our customers (except for skinning, naturally) but some of the customers wants different headers/footers/selection-logic etc. So far all the differences are handled by bloating the controls and if/else-ing all over the place.
I realize that asp.net is probably not the weapon of choice for doing this kind of thing, but it's the one we've got, and the codebase is large enough that a rewrite would be a pain.
Yes, you can load user controls dynamically using the LoadControl method. Provided that you have Control1 and a Control2, where Control2 inherits from Control1, you could do this in a page:
//Obtain control name in the format "~/pathFromApplicationRoot/ControlName.ascx"
string controlName = MethodThatDecidesTheControlNameToLoad();
//Load control
var userControl = (Control1)this.LoadControl(controlName);
//Add it to page
AControlSuchAsAPlaceHolder.Controls.Add(userControl);
Edit:
In order to be able to specify your user controls declaratively in markup I guess you could make the user control replace its own content with the tenant specific control if the config told it to override.

asp.net webforms - composite controls interacting with page controls

I am writing a composite control in c# asp.net as an experiment and would like to have all the instances of my composite control interact with one external control. Is this possible?
Things I have tried:
option 1: check from within the control whether an external control exists on the page, and add it if it doesn't
option 2: have the target control's id passed to the composite control at design time and then use this.Page.FindControl()
Obviously it was wishful thinking that it would be that simple :)
If I try do this from within the CreateChildControls Method, this.Page.FindControl(target control) always returns null. If I try to add the control to the page from within this method, it throws an exception:
"The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases."
is there another method / event where I can achieve this?
Why don't you expose a public property on your Composite Control of what output from them, then when rendering the Panel's contents, recurse through the page, find all instances of the composite control, grab the text, and add it to the panel?
You can create multiple instances on the same Web form by implementing the INamingContainer Interface. This basically helps prevent id clashes in the same namespace.
If you want to access another control set a property on it to expose the data you want made public.
Build Composite Controls

Javascript function is not working properly in Master pages

document.getelementbyid('txtbox') is not working when I used in content page as it is working in the normal web page. The value is null when it is used in contentpage. Plz anybody help me
The id will have changed, you can use something like:
document.getelementbyid(<%=txtTextBox.ClientID%>).value
or you can view the source to get the id in the hopes that it will not change again.
If you have the option I'd switch to some other engine, such as asp.net mvc where you have control over the HTML.
When the page renders, if the textBox is under another control, the Id tends to change.
You can use the ClientId property:
document.getElementById("<%= txtbox.ClientID %>")
Read this article
Control ID Naming in Content Pages
ASP.NET allows certain controls to be
denoted as naming containers. A naming
container serves as a new ID
namespace. Any server controls that
appear within the naming container
have their rendered id value prefixed
with the ID of the naming container
control.
Naming containers not only change the
rendered id attribute value, but also
affect how the control may be
programmatically referenced from the
ASP.NET page's code-behind class. The
FindControl("controlID") method is
commonly used to programmatically
reference a Web control. However,
FindControl does not penetrate through
naming containers. Consequently, you
cannot directly use the
Page.FindControl method to reference
controls within a GridView or other
naming container.
Master pages and ContentPlaceHolders
are both implemented as naming
containers.

Resources