Is there a best practice for string replacement in .aspx pages? - c#

I have an .aspx page setup. I have a lot of placeholders that need to be replaced. First name, last name, city, state, etc, etc. How do I go about doing this in an efficient manner?
Drop a bunch of...
<asp:Label runat="server" id="Label_FirstName" Text="" />
...everywhere?
Or is there a way to use the data binding syntax in the normal page area:
<% FirstName %>
Thanks in advance!

Note that
<asp:Label runat="server" id="Label_FirstName" Text="" />
will escape your strings (for example, replace < and > with < and >), but
<%= FirstName %>
will not. If that's your intention that's fine then, but be aware that you might open a channel for XSS attacks. To escape your strings properly, you might want to have
<%= System.Web.HttpUtility.HtmlEncode(FirstName) %>
instead.

You can certainly use:
<%= FirstName %>
Where FirstName is a property of the page. It doesn't necessarily have to be a property in the class, you can access pretty much anything from that line.
Update: As DrJokepu pointed out, if the data you are displaying is coming from user input, then it opens a XSS vulnerability. As was pointed out you use HtmlEncode to avoid that, in that case a more short syntax would be:
<%= Server.HtmlEncode(FirstName) %>
And if you have a base page, you can get define a method and get away with:
<%= HtmlEncode(FirstName) %>
If you go with asp.net labels, do EnableViewState = false where appropiate, so you avoid sending/receiving unnecessary viewstate.
For formatting use ids/css classes, and have the styles in a css stylesheet. The css can be cached by the browser regardless of whether the content is dynamic.
For lists of info, you can use ListView or Repeaters and still control the specific html that will be sent over the wire.

You can definitely use ASP-style tags (<%= %>) but I would argue that your first approach is cleaner and easier to maintain. When you use the ASP-style tags you will not be data binding, rather you will have access to all of the members (including fields, properties, and other methods) of the Page.
So both approaches will work if FirstName is a field or property on the Page you are working on. I personally find the control-based approach better but to each their own.

I like using labels as it is easier to mess about with colors, fonts, bolding ect... to display errors or draw the users attention to certain text.
I usually just have a set-up method in the codebehind.
if(!Page.IsPostBack)
SetupForm();
SetupForm()
{
Label_FirstName.Text = firstName;
}

You can use a bunch of labels or the Substitution control or even Literal Text if you want more control over the HTML.
You can use code in your markup like:
<%=this.FirstName%>
This will result in a property on your page called FirstName to be called and the return value from it to be placed inbetween the label.

It depends on the context in which you'll be using them. Generally using the asp:label controls is fine as you'll be able to access them from the codebehind on your page. The databinding method is generally used from within a databound control like a DataGrid or Repeater.
The real problem with the databinding method is that there isn't very good IDE support for this. To get it to work you have to have a property on your page class that you need to populate in the code behind, but if the property name changes, you'll also have to make sure you update your aspx page. If you use the labels method, the IDE will detect if there is a change in the label name, or if it has been deleted altogether and give you a compile time error.
Alternatively you could use jQuery to populate your data and just use spans as your placeholders. Be aware tho that jQuery requires a bit of a different way of thinking about your pages as it's using javascript to populate your fields.

My rules of thumb are:
If I'm labeling an input control, I use a Label so that I can set the AssociatedControlID property.
Otherwise I use a Literal or Localize control. I generally don't style Labels directly, so I don't need the extra markup they generate in other situations.
So, in your situation I'd probably use the Literal control.

Jeff Atwood explored the subject at Coding Horror and found out that performance just doesn't matter...
NOTE: it seems like Jeff posts have to be taken with a grain of salt, after all... sorry for rushing in the answer without reading the comments

Try this:
<%= FirstName %>

Related

Best way to give element custom properties in C# Webform

I have a generic html element like this
<span v-bind:class="{ available: days.timeOne }" data-time="10:00" data-date="{{ days.date }}" class="home__visit-featured-days-item-buttons-time">10:00</span>
Which when it is being rendered, is having the vuejs tags being stripped.
I have encountered this issue before when using basic html elements and even control tags like and my solution was to add them manually in the code behind. I don't like this method as not only is long and tedious, it ties back end logic to the view.
Is there a attribute similar to ClientIDMode that I can use to stop these tags being stripped?
ASP.NET webforms will strip out attributes for server controls (those with runat="server") when attributes contain colon (:) characters because these attributes cannot translate to class properties in the back end. However, non-server controls (i.e. raw markup) should just render as written into the ascx file.
Your example doesn't have a runat="server" attribute so I would expect it to render as written. If, however, it is a server control, could you just use raw markup instead?
If it must be a server control I think your only option is to add your attribute in the code behind as you mention e.g. myControl.Attributes.Add("v-bind:class", "{ available: days.timeOne }");
I suppose you are using the CK Editor for entering the HTML code. I wouldn't recommend that since it's WYSIWYG and not a code editor and does such things as stripping some part of the source. If you can, please move your code to Static text web part or to the layout directly. If you need to have it inside the editable region area, you can specify protected source for the CK Editor to let it know what code not to touch:
https://www.google.com/search?q=ckeditor%20protectedsource&rct=j

What could cause this ASP.NET tag to be treated as a string?

I recently started working with some legacy ASP.NET stuff, and I've run into an interesting problem:
I've got a table displaying a few values, some of which are evaluated in C# server-side. They all work correctly. Then all of a sudden...
<td><asp:Label ID="Label2" runat="server" class='<%=SevenDayThresholdTooHighOrLow%>'><%=ChgFromSevenDaysAgoInfo%></asp:Label></td>
ChgFromSevenDaysAgoInfo is evaluated properly.
SevenDayThresholdTooHighOrLow is rendered as a string inside of the class quotations. That is
class="<%=SevenDayThresholdTooHighOrLow%>".
In the code-behind file, the two variables are declared in the same scope, and assigned values pretty much one after the other. My Visual Studio doesn't complain about not finding certain variables in code like it would if the property did not exist.
What other factors could be influencing this oddity? What could I have missed?
Thank you very much for your help, everyone!
Eli
EDIT: I took a look at what is the use of Eval() in asp.net and tried to set my tag up that way (class='<%# Eval("SevenDayThresholdTooHighOrLow")%>'), unfortunately to no effect.
That class attribute probably isn't being evaluated for server-side code, likely because class isn't a property of Label. (Label isn't an HTML element, it's a server-side control. So instead of HTML attributes it uses object properties.)
There's a CssClass property, you might try that instead. But even then the approach is different because the system may still not attempt to evaluate server-side code injected into already server-side components. Still, worth a try.
What should definitely work is setting the CssClass property in the code-behind:
Label2.CssClass = SevenDayThresholdTooHighOrLow;
If you want to keep this out of code-behind (and who could blame you?) then another approach could be to replace the server-side control with an HTML element entirely. The idea being that if properties on this control aren't otherwise being set in server-side code, then does it really need to be a server-side control? If I remember correctly, a Label emits as a span:
<span class="<%=SevenDayThresholdTooHighOrLow%>"><%=ChgFromSevenDaysAgoInfo%></span>
You can't do that in just the markup code. You can't use server tags in a server control. You could use a data binding tag, but then you would need to trigger the data binding from the code behind anyway.
Just set the attribute from the code behind:
Label2.CssClass = SevenDayThresholdTooHighOrLow;

Repeater Vs String Builder

I think the question may seem a little weird, but here's the details.
The Goal : To retrieve a set of pairs (text, value) for various reasons. one example for that of them is retrieving the alphabet, each letter will be used as an anchor or a LinkButton, the text value will be the letter and the click event will take the value part of the pair and place it in a stringFormat() to form a "Parametrized URL"
I've used two approaches for this goal but I don't know which is better!
1. Using a Repeater
A repeater that will have a LinkButton in it's ItemTemplate and through this blocks and will set the text to the 'text' and using eval and the 'value' to create the QueryString.
2. Using StringBuilder
Create an instance of StringBuilder
Use a loop with a counter equal to the total pairs to be retrieved. and append a certain string format that will build a long string with all the needed anchors for navigation using some code like this
Links_strngBuilder.Append(string.Format("<a href='/data.aspx?page={0}'>{0}</a>", chrctr))
and finally convert the String Builder instance to a string and assign it to a label
Note: the chrctr text and value fields will be retrieved as you suggest [in each loop from the database] or [loaded in an array/arrayList/List<> to store the values and save all those connections to the db]
Where i work we will never use a stringbuild becouse of the designer. We dont want the designer in the codebehind if he has to make a simple change. so keep the markup in the view and codebehind in the codebehind.
Edit
Other advantage of repeater is the change of cycle is much easier. No need to recompile and perhaps redeploy the tweak the UI, just edit the ASPX template, save and refresh.
I don't know anything about how these two approaches perform (in terms of memory usage and speed) comparing to each other but I'd definitely go for Repeater because:
The code is much easier to understand & support
Using a StringBuilder reminds me the days of the classic ASP when the Response.Write was used widely.
You can't use any of the benefits of the Visual Designer with a StringBuilder.
-- Pavel
I think building the output fits more in client side(e.g. when you do an ajax call and want to show the results in html) than server side except when your build a custom server control.
In addition, if you use the repeater you have the extensibility option whenever requirements changed, and you have more control and facilities(like event handling and styling with css and so forth).

OnDataBinding vs Inline: pros, cons and overhead

I thought I would ask this question to see why many examples and people prefer to use inline databinding in the aspx code vs implementing an OnDataBinding event when using WebForms.
For any databound control (eg. Repeater, GridView, etc) I always implement the OnDataBinding method for field level controls if I need to do anything that isn't built in out of the box (eg. I need to do an Eval). Most examples I see have the code right in the aspx page using the inline <%# syntax.
Example of inline ASP.NET code:
<asp:Literal ID="litExample" runat="server"
Text='<%# Eval("ExampleField").ToString() %>' />
Example of how I prefer to do it:
In the aspx:
<asp:Literal ID="litExample" runat="server"
OnDataBinding="litExample_DataBinding" />
In the codebehind .cs:
protected void litExample_DataBinding(object sender, System.EventArgs e)
{
Literal lit = (Literal)(sender);
lit.Text = string.Format("{1} - {2}",
Eval("ExampleField").ToString(),
Eval("ExampleField2").ToString());
}
I personally prefer the codebehind method because it keeps my aspx pages clean and I don't have all this inline code all over the place and the next guy just knows to always look in the .cs files for code changes. The seperation of presentation and code is also maintained better this way as the HTML is place holders only and the codebind is determining what is actually being put in control.
Now these are very basic examples. The field could be a integer that you want to format with leading 0s or a DateTime that needs a specific format etc. It could also take all sort of manipulation and code to get the finally value that should be stored in the 'Text' property at the end.
Where do you draw the line and move it to the codebehind if you are using inline code?
What are the pros and cons for doing it either way?
Does one take more overhead than the other?
Edit Note: I am not talking about assigning a value to a control that is just on the page but one that is being databound to because it exists in a repeater template or gridview item template etc... Obviously a literal sitting on a page you can just assign in code.
Edit Note: I thought I would gather more response, especially with regards to the overhead. Do most people NOT use the OnDataBinding events?
I much prefer the opposite. I prefer to keep my code-behind limited to procedural code, and keep all my declarative code in my Aspx page. In your example above, the literal is absolutely declarative and therefore (by my preference) would not belong in code-behind. Much more robust functionality generally goes in my code-behind, and I don't want my developers to be cluttered by having to sift through a bunch of initialization lines when trying to understand it.
There's little performance difference between them. A data binding expression is parsed and compiles out to something like
control.DataBinding += new EventHandler(ControlDataBinding);
and also
private void ControlDataBinding(object sender, EventArgs e) {
control.Text = Eval("Field");
}
In this case, the OnDataBinding method is not overridden. The base Control.OnDataBinding method is executed, which raises the DataBinding event, causing the above code to execute.
When you override OnDataBinding, you're simply taking over before the base code is run, and get to set the Text property yourself (for example).
I dislike giving out partial answers, but I'll do it this time because I think it's neat, and it saved me recently:
I said that the data binding expression are parsed. In fact, all of the markup is parsed, code in C#, VB.NET or whatever language is generated, and this is them compiled into a class. When the page is requested, an instance of this class is created, and it begins its life.
You can locate these generated code files on disk sorry, I don't remember where. The interesting thing about them is that they still work, as code.
For instance, I recently had some fairly complex Infragistics grids set up, had all the formatting complete, and then found that I needed to be able to set the formatting at rumtime (to get the correct format into exported Excel files). In order to do this, I opened the source file (all grids were in a single user control) and was able to extract the configuration of each grid into a separate group of methods.
I was able to clean them up with ReSharper, extract common code sequences into a base class, and was left with one static method to set up each grid. I was then able to call them both for the initial setup, and for the setup of the dummy grid used for Excel export.
I prefer it your way with OnDataBinding. You can keep your codebehind clean by using a "Databind" region for all the OnDataBinding calls, and you can keep your markup clean by getting those horrible server-side code blocks out of there.
I think most people do it the inline way because it's easier to understand and to implement.
Actually I prefer to use the aspx for controls that you would expect to Bind, like listview, gridview, repeater and other similar controls.
For the other controls, I would set them in the codebehind, but directly (as part of the process I am doing, instead of calling the literal.DataBind or DataBind for the whole page). If it is an user/custom control, that I expect the callers to do a DataBind, then I would override DataBind and set the values.
That said, I usually has plenty of code outside the codebehind, and have a call to something like ShowUser, where I put those assignments to controls (instead of setting a property, then doing a bind, and having all those evals for simple controls).
I agree with caltrop. I like my markup to be clean and all my aspx/ascx code to reside in my code-behind files (where it belongs).
I only have one thing to add. I prefer not to litter my code with OnDataBinding() events wired for each of my databound controls. Instead I do it all in the OnDataBinding() event of the User Control that is being embedded in the bindable-control (such as the repeater in your sample).
For example, in my User Control's code-behind you would find:
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
litExample.Text = Eval("ExampleField") + " - " + Eval("ExampleField2");
}
From here you can set the properties of all your controls or call other methods to set them. Notice how, in my example, I didn't need to perform the boxing like you did here: Literal lit = (Literal)(sender);
That alone should save you on some performance (nanoseconds of course, but something worth measure). Read the section "Performance" here: http://msdn.microsoft.com/en-us/library/yz2be5wk%28v=vs.80%29.aspx
I am also at war with using strings in my code. I would have either used const string variables to define "ExampleField" and "ExampleField2" or set them up as public properties in the User Control that could then be set by the containing control/page based on the column name of the data object it will be bound against. This affords more flexibility and re-use of the control.
FYI: You don not need to call ToString() on Eval, as this method already returns a string.

foreach in ASP.net with nested runat="server"

For the following code:
<% foreach (Entities.Core.Location loc in locations){ %>
<div class="place_meta">
<img src="~/static/images/stars/star_25_sml.gif" runat="server" class="star_rating"/>
</div>
<% }; %>
I would like to display the star rating image for each location object displayed. However, only the first location object's star rating is displayed. For the rest, the image tag becomes <img class="star_rating" />
Am I missing anything in the syntax that allows the ability to have controls with runat=server within a foreach on the aspx page? This is with ASP.net 2.0.
I could possibly call a function in the codebehind or a display class to absolute map the URL but I am very curious if there is a solution to this problem.
Just for clarifications, the path to the image could possibly be different for each location object.
You can't use server controls within an inline loop, because ASP.NET needs to be able to uniquely identify each control to process it. The for... loop prevents this. The easiest and cleanest way is to use a Repeater control and bind your collection to it (in code-behind). Set the URL property in the bind event handler, and maintain a counter variable while binding, to check if you're at the first item or not.
Edit: I've played around with this some more, and found that if you assign an ID attribute, all looped instances get the same ID, but ASP.NET only recognizes the first control found. This would be an extremely dirty way to set properties on the first instance only. Please don't write code like this.
Unless you're using MVC, you might find a Repeater Control more useful in this situation.
If I remember correctly, you can use a source of data (your locations in this instance) and then loop through and set each image.
I don't know if your code is supposed to work, but this one is ;-)
<asp:Image ImageUrl="~/static/images/stars/star_25_sml.gif" runat="server" class="star_rating" />
Perhaps it's what you are looking for.
EDIT: looking at the code of System.Web.UI.HtmlControls.HtmlImage you can see that the src attribute is removed after the (first) processing. This may be the reason why you can get just the first URI correct with your code.
I would remove the runat="server" attribute and reference the image using a relative path (or the full path) instead of using the tilde.
EDIT: FWIW, #miies idea fits the ASP.NET paradigm AND is an example of why I'm switching to ASP.NET MVC.

Categories