Index was outside the bounds of array - Problem only After Build deployed, not in local env

Index was outside the bounds of array - Problem only After Build deployed, not in local env

Old forum URL: forums.lhotka.net/forums/t/11917.aspx


Arjun posted on Tuesday, April 02, 2013

Hi,

Our project was built based on concept "Encapsulate Invocation", which has UI, Business Layer and Data Access Layer.

And, in one of the forms a method call ends up showing the error "Index was outside the bounds of Array". I believe this happens when Business layer tries to commuicate with Data Access Layer. This occurs only when the build is deployed, but could not be reproduced in local environment. I got no clue, as I could not even debug.

Could you please suggest what could be missing ?

 

Thanks,

Arjun

 

 

RockfordLhotka replied on Tuesday, April 02, 2013

Do you have a more complete stack trace? If not, I suggest adding some more detailed logging to your solution to get the stack trace.

Arjun replied on Wednesday, April 03, 2013

Hi Rocky,

I am sorry, I could not get you the stack trace, as I cannot see the error in the dev environment. I dont have the access to the environment that gives the error. Hopefully, will get the stacktract information in couple of days. But, in mean time, Do you suggest to verify something else ?

 

Thanks,

Arjun

RockfordLhotka replied on Wednesday, April 03, 2013

With so little information I can provide no real insight.

All I can suggest is that you look at your DAL code for the business object that is failing and try to determine if the real data in production could be different from your test data and therefore would cause such an issue.

And again, adding more comprehensive runtime diagnostic log/trace monitoring will help.

Arjun replied on Thursday, April 04, 2013

Hi,

I verified the data, the test data is same in development environment and the environment where the build is deployed. So what i am left with is to add the log and move on accordingly.

Thanks for the suggestions.

Arjun. 

Arjun replied on Friday, April 05, 2013

Hi Rockey,

Here is the Stack trace.

DataPortal.Update failed (System.InvalidOperationException: One or more properties are not registered for this type ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.

   at Csla.Core.FieldManager.FieldDataManager.GetFieldData(IPropertyInfo propertyInfo)

   --- End of inner exception stack trace ---

   at Csla.Core.FieldManager.FieldDataManager.GetFieldData(IPropertyInfo propertyInfo)

   at Csla.Core.ManagedObjectBase.ReadProperty[P](PropertyInfo`1 propertyInfo)

   at CPD.ObjectLibrary.CreateFirstRequestLetterWizard.CreateFirstRequestLetterCommand.DataPortal_Execute() in E:\Provider Systems\CPD.NET\REL13xx\Development\Library\Wizard Classes\CreateFirstRequestLetterWizard.vb:line 518

   at lambda_method(Closure , Object , Object[] )

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, DynamicMethodHandle methodHandle, Object[] parameters))

Csla

   at Csla.Core.FieldManager.FieldDataManager.GetFieldData(IPropertyInfo propertyInfo)

   at Csla.Core.ManagedObjectBase.ReadProperty[P](PropertyInfo`1 propertyInfo)

   at CPD.ObjectLibrary.CreateFirstRequestLetterWizard.CreateFirstRequestLetterCommand.DataPortal_Execute() in E:\Provider Systems\CPD.NET\REL13xx\Development\Library\Wizard Classes\CreateFirstRequestLetterWizard.vb:line 518

   at lambda_method(Closure , Object , Object[] )

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, DynamicMethodHandle methodHandle, Object[] parameters)

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, DynamicMethodHandle methodHandle, Object[] parameters)

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, String method, Object[] parameters)

   at Csla.Reflection.LateBoundObject.CallMethod(String method)

   at Csla.Server.SimpleDataPortal.Update(Object obj, DataPortalContext context)

   at Csla.DataPortal.Update[T](T obj)

   at CPD.ObjectLibrary.CreateFirstRequestLetterWizard.CreateFirstRequestLetter() in E:\Provider Systems\CPD.NET\REL13xx\Development\Library\Wizard Classes\CreateFirstRequestLetterWizard.vb:line 54End of Main message

 

DataPortal_Execute method call failed

Csla

   at Csla.Core.FieldManager.FieldDataManager.GetFieldData(IPropertyInfo propertyInfo)

   at Csla.Core.ManagedObjectBase.ReadProperty[P](PropertyInfo`1 propertyInfo)

   at CPD.ObjectLibrary.CreateFirstRequestLetterWizard.CreateFirstRequestLetterCommand.DataPortal_Execute() in E:\Provider Systems\CPD.NET\REL13xx\Development\Library\Wizard Classes\CreateFirstRequestLetterWizard.vb:line 518

   at lambda_method(Closure , Object , Object[] )

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, DynamicMethodHandle methodHandle, Object[] parameters)

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, DynamicMethodHandle methodHandle, Object[] parameters)

   at Csla.Reflection.MethodCaller.CallMethod(Object obj, String method, Object[] parameters)

   at Csla.Reflection.LateBoundObject.CallMethod(String method)

   at Csla.Server.SimpleDataPortal.Update(Object obj, DataPortalContext context)

 

I am glad we are able to solve this issue. The root cause is wrong use of property.

PublicShared ReadOnly NameProperty As PropertyInfo(Of Long) = RegisterProperty(Of Long)(Function(c) c.Id,"Id")

Public ReadOnly Property Id() As Long

Get

Return ReadProperty(IdProperty)

End Get

End Property

Here you can observe, the registered property is Name, but used Id property. This has caused the defect in server. But I really dont understand why this has not caused issue in Local environment.The above mentioned property is in commandbase class, the Id property is also avaliable in parent class of this command base class. I assume, It read the IdProperty from its parent as it could not find it in the command base class.

Anyway, Thank you very much for your directions.

 

Arjun

 

 

 

 

RockfordLhotka replied on Friday, April 05, 2013

You have to be extremely careful about using inheritance with properties - I generally recommend avoiding it because it can cause bugs like this one.

You can't register a property of the same name twice in the same type, because that'll confuse the field manager. The name of the static variable has no meaning, it is the name of the property that can't be duplicated.

skagen00 replied on Friday, April 05, 2013

From my experience, inheritance with properties has been relatively safe **as long as the base class is abstract** (which typically these type of base classes are).

My understanding is that there is a bit of compiler wizardry happening under the hood with statics and inheritance, but we have a few base classes that leverage properties that end up getting leveraged in concrete implementations for certain base class functionality we've built out.  It works well for us.

Arjun replied on Monday, April 08, 2013

Yes, you are right.

But, it is a command base class which, I assume, cannot be written outside a business base. We are calling the command base class from the public method of the business base. To pass the values, we have two sets of parameters one in Business base and other in Command base. The values are taken first to business base properties so that public method will be called without any parameters. And in the public method, we pass the values to the second set in command base.

If the class structure is like this, 

Public Class Employee

<Properties> ID, Name

public sub MarkAsExcellent()

      cmd = ExcellentCommand(Me.ID, Me.Name)

End Sub

 

Private class ExcellentCommand

     inherits CommandBase(Of ExcellentCommand)

<Properties>ID,Name

- DataPortal_Execute() -

End Class

 

End Class

 

From the UI, code is like this.

_Employee =  Employee.NewItem(10,"Arjun")

_Employee.MarkAsExcellent()

 

Taking this as the scenario, I had no choice using the same names in both the places as these are the best suited names. And about inheritance, Is there any other way to use Command base class ?

 

Thanks,

Arjun

RockfordLhotka replied on Monday, April 08, 2013

What you are showing here is not an inheritance hierarchy, it is just nested classes. So you don't have ID defined in a base class - you have ID defined in two separate classes, one of which happens to be nested inside the other (which is really just a namespace thing, nothing more).

So then the question is whether you are properly using managed property declarations in your command class?

Arjun replied on Tuesday, April 09, 2013

Hi Ricky,

The question is, Why is it not throwing any exception in local environment, even when the property is not registered properly. Is it because of the property ,with the same name, in outer class ?

 

 

RockfordLhotka replied on Tuesday, April 09, 2013

Is you local environment configured the same as production?

In other words, is the local environment using a remote data portal? Configured the same? Running Release mode code, not Debug code?

Arjun replied on Wednesday, April 10, 2013

The only thing i can tell you is, it is not running in Release mode rather it is running in Debug mode. would you mind telling me what remote data portal is?

And for deployment, we use two servers. UI is deployed in one server and BO, Data access DLLs are deplpoyed in other server. Web service is the one that makes the two servers communicate. So, do you think this configuration makes the difference ?

 

JonnyBee replied on Monday, April 08, 2013

Hi,

You can write ComandBase derived classes as own class files - absolutely no problem. There is NO must to have it within a BusinessBase class. 

_u152 replied on Tuesday, May 07, 2013

I had a similar issue while implementing the paste clipboard operation using the CSLA 3.5 Business Object (BO), although we have a customized version of the framework.

 

Scenario to reproduce my issue:

1. Copy the BO to the clipboard (clone BO, but change relevant BO ids to generate unique root and child objects).

2. Restart the application

3. Paste the Business Object from the clipboard (eventually calls BusinessBase<T>.Save() and tries to save properties)

Expected result: Business Object is pasted/saved and it's representation shows in the UI.

Actual result:

DataPortalException: ChildDataPortal.Update failed on the server ---> CustomFramework.Reflection.CallMethodException: Child_Insert method call failed ---> System.InvalidOperationException: One or more properties are not registered for this type ---> System.IndexOutOfRangeException: Index was outside the bounds of the array.

 

The solution:

Before saving, to register the static properties, create a dummy instance of the type for which the static properties are not registered.

e.g. To ensure IdProperty is registered, call MyProblemClass.RegisterProperties()

public class MyProblemClass: BusinessBase<MyProblemClass>

{

        private static PropertyInfo<Guid> IdProperty = RegisterProperty<Guid>(new PropertyInfo<Guid>("Id", "FriendlyId"));

        public Guid Id

        {

            get

            {

                return GetProperty<Guid>(IdProperty);

            }

 

            set

            {

                SetProperty<Guid>(IdProperty, value);

            }

        }

 

        public static void RegisterProperties()

        {

            // No need to keep a reference,

            // we only want to register the static properties.

            MyProblemClass.NewDummy();

        }

 

        /// Typical method to create a new instance

        public static MyProblemClass NewDummy()

        {

     MyProblemClass model = DataPortal.CreateChild<MyProblemClass>(new CriteriaCreate() { ... );

            return model;

        }

}

Copyright (c) Marimer LLC