Living in Code

Ramblings from a code monkey

FormView and ObjectDataSource with nullable types

I recently ran into this problem when using a FormView and and ObjectDataSource where the FormView was binding to nullable data types...

Here is a challenging question, as I have not found any suitable information on this after two days of searching:

Background:

I have a custom Business Class library that includes custom objects with nullable int and DateTime properties. In order to update this data, I have created a FormView control bound to an ObjectDataSource that retrieves a generic List collection of my business objects. The reflection that is intrinsically called by the FormView/ObjectDataSource combination dutifully builds my basic Select, Update, and Insert templates. Now, when you edit the various (TextBoxes by default) input fields and then call the Update method referenced in the ODS (ObjectDataSource), the ODS attempts to convert the data contained in the input fields to the corresponding Type of the property bound to said input field. This is where we run into our little problem...

Even though I have a nullable Integer property type (let's call it int? ClassNumber), if the corresponding TextBox is empty (since it's not required), an exception is thrown by the ODS since it tries to convert an empty string value to an integer value before trying to set the object's Property. Hah! If ODS was able to determine that the integer is in fact nullable, it should pass in a null value instead! But alas, it throws a System.IndexOutOfRangeException: "Index was outside the bounds of the array" error. And further down the stack: "Exception: is not a valid value for Int32". Hmmm. Since this is a FormView control, we don't have the ability to use a BoundField control with 2 very useful properties: NullDisplayText and ConvertEmptyStringToNull. It would be nice to tell ODS to enable sending null values from any control we want.

 

The above was posted originally here.  I used his clipping because it describes perfectly the problem I had, along with many, many others. 

After hours and hours of Googling and trial and error I finally found the solution to this.  There was no way in hell I was going to accept the solution of manually re-populating each field I had bound in my edit and insert templates for my FormView.  The solution was much easier and left all of the heavy lifting to the FormView.

Basically, all you have to do is all insert and update parameters in your ObjectDataSource for each field you're binding.  For these fields, you just need to supply the field name, the data type and set the ConvertEmptyStringToNull property to TRUE.  Also, you'll need to be sure to set the ConvertNullToDBNul property to TRUE in the ObjectDataSource itself, like below. 

<InsertParameters>
<asp:Parameter Name="TimeZoneOffset" Type="int32" ConvertEmptyStringToNull="true" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="TimeZoneOffset" Type="int32" ConvertEmptyStringToNull="true" />
</UpdateParameters> 

 
So just by adding these parameters for the insert and update you can have your FormView's databinding work with nullable types.  Not too bad, huh?

Currently rated 5.0 by 5 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET
Posted by Don on Sunday, July 15, 2007
Permalink | Comments (21) | Post RSSRSS comment feed

FormView not retaining values when server-side validation fails

I recently spent quite a bit of time trying to figure out why my FormView wasn't retaining values after some of my custom server-side validation failed in my business logic layer.  I kept seeing that you just had to set KeepInEditMode = true (or KeepInInsertMode if you're doing an insert) and that would take care of it.

Well, after a lot of trial and error and hours googling and reading messages forums I finally found the answer.  Before I go into what I needed to do to fix it, I'll give a little bit of background.

I am using a FormView with an ObjectDataSource.  The ObjectDataSource maps to our business logic layer for the Select, Insert and Update methods.  Initially, the insert and update methods were returning an "envelope" object that contained a list of any BLL errors that were caught from server-side validation.

Everything worked fine using this approach except for retaining the values in the FormView that the user had changed before the last insert or update action.  I couldn't for the life of me figure out why the FormView kept re-initializing the data even though I didn't actually save anything to the DB in the BLL.

Well, it turns out that my approach of returning an envelope just wasn't cutting it.  What I had to do was throw an exception from the BLL class back to the calling page so that the FormView's ItemInserted and ItemUpdated events would keep the old data around.

Here's what I ended up with...

If Not e.Exception Is Nothing Then
     e.ExceptionHandled = True
     e.KeepInEditMode = True           
CType (Master, Site).ShowErrorPopup("Errors:", e.Exception.InnerException.Message) End If

If it doesn't see an exception, it thinks that the operation before (insert or update) was successful and it doesn't keep the old data around.  It goes and reinitializes the FormView with the select again.

So in my BLL I simple got rid of my envelope that I was passing back and built a new exception.  It's use is as follows:

Dim brokenRules As New StringBuilder
brokenRules = ValidationManager.ConsolidateBrokenRules(oneEntity.BrokenRulesList, brokenRules)
Throw New Common.EntityValidationException(brokenRules.ToString)

The new exception paired up with a class in the Master Page to display the errors to the user (via the AJAX Control Toolkit's Modal Popup Extender ) took care of my problems.

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: ASP.NET
Posted by Don on Friday, July 13, 2007
Permalink | Comments (4) | Post RSSRSS comment feed