Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Eval in aspx only if property exists in item - throws DataBinding exception

Tags:

c#

.net

asp.net

I have an aspx page that has a repeater with 5 fields. Those fields are filled with two different item types. One item has 3 properties : "A" "B" "C" and the other has "A" "B" "C" "D" "E".

I want to use the same repeater for both but show only the relevant properties for each of them. When trying to use Eval on a propery "D" with item 1 i get the error: DataBinding: 'Item1' does not contain a property with the name 'D'.

I tried to use if statement but it did not help and when trying to use "ItemDataBound" event it also throws exception when trying to load Item1 (not throwing when trying to load Item2 with all the properties.

How can i Eval only if property exists?

like image 931
FelProNet Avatar asked Feb 08 '15 10:02

FelProNet


1 Answers

To solve your issue it is important to understand how Eval works under the hood.

The Eval statement is converted to call to DataBinder.Eval method on aspx compilation stage. This means that expression <%# Eval("A") %> is a shortened version of <%# DataBinder.Eval(Container.DataItem, "A") #>. If you will follow the execution path of Eval method you'll see that exception is thrown in GetPropertyValue if container object does not contain a property:

// get a PropertyDescriptor using case-insensitive lookup
PropertyDescriptor pd = GetPropertiesFromCache(container).Find(propName, true);
if (pd != null) {
    prop = pd.GetValue(container);
}
else {
    throw new HttpException(SR.GetString(SR.DataBinder_Prop_Not_Found, container.GetType().FullName, propName));
}

To suppress the exception thrown by Eval you can write your own SafeEval method and put it in your base page class:

public abstract class BasePage: Page
{
    public object SafeEval(object container, string expression)
    {
        try
        {
            return DataBinder.Eval(container, expression);
        }
        catch (HttpException e)
        {
            // Write error details to minimize the harm caused by suppressed exception 
            Trace.Write("DataBinding", "Failed to process the Eval expression", e);
        }

        return "Put here whatever default value you want";
    }
}

Then use it inside repeater:

<asp:Label runat="server" Text='<%# SafeEval(Container.DataItem, "A")  %>'></asp:Label>

While this will solve your issue this will expose another issue such as absence of error notifications when binding expression is really wrong/mistyped. So I would suggest to have two different repeaters for each item type instead of trying to find the workaround for the standard ASP.NET Eval behavior.

like image 164
Alexander Manekovskiy Avatar answered Sep 27 '22 19:09

Alexander Manekovskiy