Tuesday, February 10, 2009

Persisting Data in User Controls with ViewState

In ASP.NET, the ViewState is used to persist data across requests. Let's say, for example, I want to use a User Control that will show information based on a particular date. I could create a property in that control that looks like this:
private DateTime _Date;
public DateTime Date
{
set
{
_Date = value;
ViewState["Date"] = value;
}
get
{
if (_Date.Ticks == 0 && ViewState["Date"] != null)
{
_Date = (DateTime)ViewState["Date"];
}
return _Date;
}
}
... which would make it possible for me to "set and forget" the date from the page containing that user control. For example:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
AddTrackedTime1.Date = DateTime.Today;
}
}
So the first time the page loads, it sets the user control's date. You could have events set up to change the date on that user control if you want. Each time the date gets set, it will add a binary value to the ViewState, which will persist in the form of a hidden field on the webpage that is being viewed. When the time comes to do something with that date value, it will automatically be loaded out of the ViewState. Because the viewstate is persisted in a hidden form field, it will continue to work properly even if the user clicks "back" several times in the browser and then clicks on a control from their browsing history. Also, unlike the Session, the ViewState is specific to the control instance, so you could have several of these controls on the same page and they wouldn't step on each others' toes.

The only potential downside is that you increase the amount of data sent to and from the browser, which could slow transactions somewhat.

Wednesday, January 21, 2009

Asp.net DataObjectSource + Gridview difficulty

Here are some annoyances I encountered recently while trying to get some basic data binding to work in ASP.NET:

I was using an ObjectDataSource to access objects through our data access layer, and then displaying the data in a Gridview. After some tweaking, I got it to display all right, but when I clicked "Edit" and then "Update" I ran into all kinds of issues. First it wouldn't link up right to my data access layer, because it was looking for a method that included the Name and Description fields. After some digging around, I found out that the "Default" method it looks for is one with only an object (in this case of a type called TrackedEntity) as a parameter. But because the data access layer's default add/update/delete methods also include a boolean parameter to tell it whether or not to Save the updated changes (though I have a hard time imagining why you wouldn't want it to, if you're calling the Update method), ASP.NET got kicked out of this default object-oriented mode, and started looking instead for a method that took all the parameters it knew about, plus the ones that I specified. Fix: create an update method that only takes a TrackedEntity, and point the ObjectDataSource to that method.

After this, however, it still couldn't update correctly because the TrackedEntity object it was updating was only getting instantiated with its Name and Description (and not its ID). So when the data access layer tried loading up the object to update, it couldn't find an object with an ID of zero, so it died.

As a work-around, I found that simply including the ID column in the GridView would do the trick, but that's a hack, at best. After much searching, I found out that GridViews have a DataKeyNames property, in which you can include a comma-separated list of fields that shouldn't be shown in a column, but which need to be persisted so that the object being saved gets instantiated with all its previous values.

Finally, if I left any of the fields blank, it would complain that the values could not be null.  By default, Gridviews will convert empty strings to null values.  I had to put the following attribute in each BoundField: ConvertEmptyStringToNull="False".  Whew!

If programming languages were religions

Our company's CTO sent this to us after we had made the decision to switch to .NET and start using C# as our programming language on a new product we've started working on:

I thought it was pretty funny and appropriate, in light of my other, more personal blog, "Adventures in Mormondom."  Here's an excerpt:

C would be Judaism - it's old and restrictive, but most of the world is familiar with its laws and respects them. The catch is, you can't convert into it - you're either into it from the start, or you will think that it's insanity. Also, when things go wrong, many people are willing to blame the problems of the world on it.

Java would be Fundamentalist Christianity - it's theoretically based on C, but it voids so many of the old laws that it doesn't feel like the original at all. Instead, it adds its own set of rigid rules, which its followers believe to be far superior to the original. Not only are they certain that it's the best language in the world, but they're willing to burn those who disagree at the stake.

...

C# would be Mormonism - At first glance, it's the same as Java, but at a closer look you realize that it's controlled by a single corporation (which many Java followers believe to be evil), and that many theological concepts are quite different. You suspect that it'd probably be nice, if only all the followers of Java wouldn't discriminate so much against you for following it.

Introduction

At work, we're transitioning from Java technologies to .NET technologies. We've started a little project to help us get up to speed on .NET, and I have spent enough time on a couple of bugs that I figured I'd write about them to help anybody else who might run into similar problems.

I plan to use this blog as a place to post interesting things that I learn as we transition into .NET-dom.