Setting CDF Description

Discussions related to SoftPro Select user interface development.

Moderator: Phil Barton

Post Reply
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Setting CDF Description

Post by dlerickson »

I'm trying to set the "Description" property on an existing OriginationChargeDetailLine. There are two issues that I'm running into:

1. Calling [IOrderItem].GetIsCalculated("Description") is returning true, but the Description value is null. Why is this?
2. Calling [IOrderItem].SetProperty("Description", "Origination Fee") throws the following Exception: "Cannot access a disposed object.
Object name: 'OriginationChargeDetailLine'."

Is this some sort of templating issue, or what needs to be done to make this work correctly? I've done this in previous versions of the code with no issues.
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Setting CDF Description

Post by BobRichards »

I need more context. It looks like the OriginationChargeDetailLine may not be a valid object since some of the properties are disposed. Did you drill down the CDF to find this object or did you create a new object?
Bob Richards, Senior Software Developer, SoftPro
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Setting CDF Description

Post by dlerickson »

Here is a bit of context as to what I'm doing: I have an XML-based configuration document that dictates the drill-through at runtime. Here's the relevant snippet:

Code: Select all

      <Node name="CDFs" active="true">
          <Handler type="EscrowCollection" target="CDFs" method="Index" />
          <Nodes>
            <Node name="CDF" active="true" index="0">
              <Handler type="Generic" target="CDF" />
              <Nodes>
                <Node name="OriginationCharge" active="true">
                  <Handler type="Generic" target="OriginationChargeSection" />
                  <Nodes>
                    <Node name="Lines" active="true">
                      <Handler type="Collection" target="Lines" method="Match" matchField="Description" />
                      <Nodes>
                        <Node name="A01Line" active="true" index="1" matchField="Number">
                          <Handler type="CdfLine" active="true" target="OriginationChargeDetailLine" />
                          <Fields>
                            <Field key="TestNumber" target="Number" rule="Optional" readOnly="true" active="true" description="CDF Line Number (Testing purposes only)" />
                          </Fields>
                          <Nodes>
                            <Node name="A01Charges" active="true">
                              <Handler type="Collection" target="Charges" method="Index" />
                              <Nodes>
                                <Node name="A01Charge1" active="true" index="0">
                                  <Handler type="Generic" target="" />
                                  <Nodes>
                                    <Node name="A01Calculation" active="true">
                                      <Handler type="Generic" target="Calculation" />
                                      <Fields>
                                        <Field key="PercentOfLoanAmt" target="Percent" rule="Optional" readOnly="true" active="true" description="Percent of Loan Amount" />
                                      </Fields>
                                    </Node>
                                  </Nodes>
                                </Node>
                              </Nodes>
                            </Node>
                          </Nodes>
                        </Node>
The engine we have deserializes this document into an object tree, and each node instantiates and contains a Handler subtype, which is responsible for finding and mapping the appropriate IOrderItem instance in the tree. The code is this for the "Generic" handler:

Code: Select all

APIObject = ((IOrderItem)Parent.APIObject).GetProperty(Node.Handler.Target);
In this snippet, "Node.Handler.Target" is just a string in the config document that defines the name of the property to get. For collections, it's a bit more complex, as the child nodes to the collection can be set up either by straight Index, or by field match (XPath definition: //Handler[@method='Index|Match']). the matchField then dictates what IOrderItem field to perform the match on.

So, all that having been said, here is the yield of the drill-through, to the CDF Line level, with the object name and type:

CDF (type CDF) ->

OriginationChargeDetailSection (type OriginationChargeDetailSection) ->

Lines (full type name is SoftPro.EntityModel.Collections.Set`1[[OriginationChargeDetailLine, SoftPro.OrderTracking.Order_ab58e2dfbb0280044a25794465b4fb6f, Version=4.3.60108.11, Culture=neutral, PublicKeyToken=8ae96314b6bae08d]]) ->

(Target line), type OriginationChargeDetailLine.

------
In the particular order that's giving me trouble, I'm not instantiating any IOrderItem objects, just polling over what already exists in the order. One complication with CDF lines is that we're trying to match the Description field to an existing line (except in the case of A.01, which matches on number), and if that fails, iterating through the Lines collection to find the next available line without a description, and attempting to set the Description field there. This is where the problem lies: the field is marked as calculated. The template that I'm using has plenty of CDF lines for that section already set, and only the A.01 one has the Description pre-set. So, I should not have to create a new Line at any time for our purposes.
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Setting CDF Description

Post by dlerickson »

Hi Bob,

I've implemented the changes we spoke about the other day. Now I'm seeing a new issue. Anytime I call SetProperty on any IOrderItem at any level, I'm getting an ObjectDisposedException which originates from SoftPro.EntityModel.dll.

Example message: "Cannot access a disposed object. Object name: 'Loan'."

Stack Trace:

Code: Select all

   at SoftPro.EntityModel.Entity`1.ThrowIfDisposed()
   at SoftPro.EntityModel.Entity`1.SoftPro.EntityModel.IEntity.SetProperty(String path, Object value)
   at Loan.SoftPro.OrderTracking.Client.Orders.IOrderItem.SetProperty(String , Object )
   at Title.ClientIntegration.Overlay.Application.Processing.OrderItemHelper.TrySetProperty(IOrderItem orderItem, Object value, String propertyName)
   at Title.ClientIntegration.Overlay.Application.Processing.Handlers.BaseHandler.WriteField(IOrderItem orderItem, OverlayField field)
This occurs for *any* property that I try to set at any level.

For reference, the OrderItemHelper.TrySetProperty code is as follows:

Code: Select all

        public static SelectPropertyState TrySetProperty(IOrderItem orderItem, object value, string propertyName)
        {
            var state = GetPropertyState(orderItem, propertyName);

            switch (state)
            {
                case SelectPropertyState.OK:
                    orderItem.SetProperty(propertyName, value);
                    break;
                case SelectPropertyState.Calculated:
                    // NOTE: sometimes a calculated field can be overwritten. Attempt to set, and fail gracefully if not.
                    try
                    {
                        orderItem.SetProperty(propertyName, value);
                        return SelectPropertyState.OK;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                    break;
                case SelectPropertyState.Invalid:
                    break;
                case SelectPropertyState.Locked:
                    break;
                case SelectPropertyState.ReadOnly:
                    break;
                case SelectPropertyState.Unsupported:
                    break;
                default:
                    return SelectPropertyState.Invalid;
            }

            return state;
        }
...with SelectPropertyState just being an Enum value that is returned from GetPropertyState, which just runs through the various IOrderNode checks (HasProperty, GetIsSupported, etc.)

the order should be in scope, as I'm doing all the processing within a "using (var order = store.OpenOrder(info))" block, so I'm not sure what's going on to cause the problem. Any ideas?
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Setting CDF Description

Post by BobRichards »

"TrySetProperty" is not a method for doing what you are wanting. It is used in a very different setting.

Use the methods associated with IOrderItem for interacting with IOrderItem properties and attributes.
Bob Richards, Senior Software Developer, SoftPro
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Setting CDF Description

Post by dlerickson »

Sorry for the confusion; "TrySetProperty" is a static method that I had coded in a helper class that wraps some extra logic around internal calls to the standard [IOrderItem].SetProperty call, and is not a direct call into the API itself. You should see the inner call in the code snippet there. I was just including my method for context, so you could see what was involved with the stack trace.
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Setting CDF Description

Post by BobRichards »

I will review your post again. I just want you to know that I finished two HowTo's on our Best Practices for accessing IOrderItem properties. Didn't know if you would be interested: How to Read from IOrderItem Properties and How to Write to IOrderItem Properties.
Bob Richards, Senior Software Developer, SoftPro
Post Reply