Does ASP.NET always apply the "ct100$..." prefixes to element IDs, or in some cases does it optimize this away if the element is guaranteed unique anyways.
Recently I have seen builds differing in the ID prefixes being applied, one having the prefixes and one not but both deriving from the same source.
Can anyone provide any more detail this, and on the workings of INamingContainers and ID generation?
The new ASP.NET 4 ClientIDMode property affects the client-side ID rendered. Setting the naming container control to Predictive is meant to cut down on this... Static takes the exact ID and renders to the client, which you have to be careful to ensure uniqueness.
When you use a naming container (a master page is also a naming container), it appends this longer ID to ensure uniqueness; with .NET 4, they thought a little more about this and added features like Predictive and Static to cut down on the lengths of the IDs.
HTH.
Related
I'm attempting to use client-side validation in an admin page in Orchard. I've been successful at making it work using the techniques discussed in this question, but after doing some digging in the Orchard source and online, it seems to me that commenting out these lines
// Register localized data annotations
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider());
is subverting some built-in Orchard functionality which allows for localized error strings. At this point, either having these lines in our out of OrchardStarter.cs is the only difference between validation working and not working for me.
What I'm hoping for is some guidance on this, maybe from the Orchard team. If these lines have to be out in order for validation to work, why are they there in the first place? If they are there for a good reason, what am I (and others) doing wrong in our attempts to get client-side validation working? I'm happy to post code samples if needs be, although it's a pretty standard ViewModel with data annotations. Thanks.
The lines are there to replace the DataAnnotationsModelValidatorProvider (DAMVP) with Orchard's own implementation, which allows localizing the validation messages the Orchard way. The way it does this is by replacing e.g. [Required] with [LocalizedRequired] before passing control on to the DAMVP. Note that DAMVP does get to do its job - but only after Orchard has "messed" with the attributes.
The problem is that DAMVP uses the type of the Attribute to apply client validation attributes. And now it won't find e.g. RequiredAttribute, because it's been replaced by LocalizedRequiredAttribute. So it won't know what - if any - client validation attributes it should add.
So, out-commenting the lines will make you lose Orchard's localization. Leaving them in will make you lose client validation.
One workaround that might work (haven't looked enough through Orchard's code, and haven't the means to test at the moment) would be to make DAMVP aware of Orchard's Localized attributes and what to do with them.
DAMVP has a static RegisterAdapter() method for the purpose of adding new client rules for attributes. It takes the type of the attribute and the type of the Client-side adapter (the class that takes care of adding client attributes) to use.
So, something like the following might work:
In OrchardStarter.cs:
// Leave the LocalizedModelValidatorProvider lines uncommented/intact
// These are the four attributes Orchard replaces. Register the standard
// client adapters for them:
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedRegularExpressionAttribute),
typeof(RegularExpressionAttributeAdapter)
);
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedRequiredAttribute),
typeof(RequiredAttributeAdapter)
);
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedRangeAttribute),
typeof(RangeAttributeAdapter)
);
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedStringLengthAttribute),
typeof(StringLengthAttributeAdapter)
);
As for the official word, it would seem this hasn't worked since localized validation was introduced in 1.3, and the impact is considered low: http://orchard.codeplex.com/workitem/18269
So, at the moment, it appears the official answer to the question title is, "it shouldn't".
I'm trying to make sense of the following select element :
<select name="ctl00$ctl00$ContentPlaceHolder1$ContentItems$ddlResponseRange id="ctl00_ctl00_ContentPlaceHolder1_ContentItems_ddlResponseRange" class="Content" style="width:11%;">
This is all automatically generated code, correct( ie like ct100 ) ? What are the $ symbols doing - are they for expression bindings? FYI the ddl here means "drop-down list".
$ and _ are used as separators between the server-side ID of the control, ddlResponseRange, and the server-side IDs of its parent controls that are of type INamingContainer (typically <asp:content> controls).
A control by itself on a page, right inside a <form runat="server"> does not have attributes like that. But when you start using master pages, or data binding controls, then you are using controls that implement INamingContainer. This interface is like a marker, and it instructs the ASP.NET runtime to start adding the control's server-side ID to that of its child controls. This is necessary to guarantee unique name and ID attributes in the generated HTML.
Ultimately this infrastructure is what supports ASP.NET Web Forms post back mechanism and client-side scripting.
If you are using ASP.NET 4.0 or later, you can actually influence the way client-side IDs are generated by ASP.NET. See this article for different ways to configure the client-side IDs.
It's all just one big string. From the point of view of HTML, they're all valid characters to make up the value of an attribute, so in that sense it's "correct".
As for trying to use the id/name value yourself, or to rely on assumptions about the name/id based on that structure, I'd suggest avoiding that. I find it preferable to pretend that ASP will generate a random name/ID that I can't use, despite the fact that in reality it's just the IDs of all elements from that item up to the root. If you find yourself writing out ID values like that yourself, you're probably doing something wrong.
As for why it follows that convention instead of just actually assigning a random ID/Name (or none at all) is so that it can re-use it to correlate the HTML response to the structure of of items in memory. It's also important to ensure that IDs are unique per page, and by using this structure it means that APS ID values only need to be unique among sibling elements.
Fluent builder is a well-known pattern to build objects with many properties:
Team team = teamBuilder.CreateTeam("Chelsea")
.WithNickName("The blues")
.WithShirtColor(Color.Blue)
.FromTown("London")
.PlayingAt("Stamford Bridge");
However, using it doesn't seem very clear to me due to one particular reason:
Every Team object has its minimal operational state, in other words, set of properties which have to be set (mandatory), so that the object is ready to use.
Now, how should the Fluent builder approach be used considering that you have to maintain this state?
Should the With_XYZ members modify the part of the object, that can't affect this state?
Maybe there are some general rules for this situation?
Update:
If the CreateTeam method should take the mandatory properties as arguments, what happens next?
What happens if I (for example) omit the WithNickName call?
Does this mean that the nickname should be defaulted to some DefaultNickname?
Does this mean that the example (see the link) is bad, because the object can be left in invalid state?
And, well, I suspect that in this case the fluent building approach actually loses it's "beauty", doesn't it?
CreateTeam() should have the mandatory the properties as parameters.
Team CreateTeam(string name, Color shirtColor, string Town)
{
}
Seems to me the points of Fluent Interface are:
Minimize the number of parameters to zero in a constructor while still dynamically initializing certain properties upon creation.
Makes the property/ parameter-value association very clear - in a large parameter list, what value is for what? Can't tell without digging further.
The coding style of the instantiation is very clean, readable, and editable. Adding or deleting property settings with this formatting style is less error prone. I.E. delete an entire line, rather than edit in the middle of a long parameter list; not to mention editing the wrong parameter
So I just learnt about the Triplet class. I have no experience with ASP.NET, only the core .NET Framework.
Can someone explain to me where/why the Triplet class exists? Is it like a Tuple?
Yes, it's pretty much like Tuple from .NET 4.0, but dates back to .NET 1.0 and ASP.NET 1.0 in particular. It's primarily used in ViewState serialization:
The Page class contains a SavePageViewState(), which is invoked during the page life cycle's save view state stage. The SavePageViewState() method starts by creating a Triplet that contains the following three items:
The page's hash code. This hash code is used to ensure that the view state hasn't been #tampered with between postbacks. We'll talk more about view state hashing in the "View State and Security Implications" section.
The collective view state of the Page's control hierarchy.
An ArrayList of controls in the control hierarchy that need to be explicitly invoked by the page class during the raise postback event stage of the life cycle.
There's also its' younger brother called Pair.
There's absolutely no reason you should even bother about these classes or else an unholy untyped mess will ensue.
Sounds like it's got one more object than a Pair. You use it when you need to return exactly three items.
C# and Java are different from Python, which will convert multiple return values into a tuple.
A Triple does sound like a tuple to me - one that has exactly three items.
Does anyone have any guidelines/best practices for naming conventions for Forms and controls (e.g., events, buttons)?
I usually use Systems Hungarian notation
Example:
btnSubmit: is button
lblAccountNum : variable is a label
In WinForms I usually use suffixes, so for example:
submitButton
accountNumberLabel
etc.
But a lot of companies still use a prefix, like anthares said.
I don't believe any special rules are needed for forms development; the Microsoft .NET naming guidelines cover it.
I name forms like any other class in the application: MainForm, SaveDialog, etc.
I name controls like any other field within a class: okButton, nameTextBox, etc.
I usually prefix the full class name e.g. textBoxName. I find it easier to read than three letter prefixes and it's consistent with the names that are generated by the IDE. I only name controls that are referred to by code. Controls that are databound usually don't need a name.
The following example is most of the .net programmer is used
Control: Label
Prefix : lbl
Example: lblFirstName
The reason that the prefixes are not the full class names in most of the companies but some abbreviations of the class name are as follows:
Most of the naming conventions are approved before Visual Studio 2010.
All Visual Studio versions before 2010 have their inteli sense filter with something like "starts with" instead of contains.
That's why a lot of people / architects / leaders decided it will be a better idea to type "txt" and inteli sense will filter all textboxes for you, so then you just type "E" for example and you get txtEmail. If you have the full class name, you will need to type "textBoxE" to get the same result in inteli sense. This adds a lot of overheat when you have complex UI.
Now with Visual Studio 2010 you get a better inteli sense so you can just type "em" and you can easilly see the "textBoxEmail" in the list (along with Email and some other things that contain "em"). Still I seem to prefer to have 2-3 or up ot 4 letters abbreviation that will allow me to filter in inteli sense by control type (specially for UI) than having to type textBox. The reason I prefer it is that even if you are puzzled for a while with some control type (e.g. "rg" for RadGrid) you will need 5 minutes 3-4 times to remember it and start typing without thinking about it. While if you have radGrid everywhere you will need to hit 7 strokes to get to the meaningful one that will filter for you (e.g. "radGridC" in "radGridCustomers").
I do agree that only naming controls that are referenced in the code is usually enough.