Error when using decimal type in RemObjects.SDK.Types.ComplexType

I have a simple service that uses the following type:

[Description("UserData holds information about a user")]
public class UserData : RemObjects.SDK.Types.ComplexType
{
    [Description("lName user last name")]
    public string lName { get; set;}
    [Description("fName user first name")]
    public string fName { get; set; }

    [Description("userID user ID number")]
    public string userID { get; set; }

    [Description("myEnum enum of user capibilities")]
    public MyEnum myEnum { get; set; }

    [Description("hotelCode string array of hotel codes")]
    public string[] hotelCodes { get; set; }

    public decimal decimalTest { get; set; }
}

This type is returned with the following service method:

   [ServiceMethod, Description("DoSomething returns UserData")]
    public UserData DoSomething(UserData s)
    {
        s.userID = "123";
        s.myEnum = MyEnum.Two;
        s.hotelCodes = new string[2] { "Hotel1", "Hotel2" };
        s.decimalTest = 3.14M;
        return s;
    }

When called I get the an error in my _inf file at this location:

       else {
            decimalTest = serializer.ReadDecimal("decimalTest");  <<<+++ exception
            fName = serializer.ReadUtf8String("fName");
            hotelCodes = ((string[])(serializer.Read("hotelCodes", typeof(string[]), RemObjects.SDK.StreamingFormat.Utf8String)));
            lName = serializer.ReadUtf8String("lName");

The exceptions details are:

System.ArgumentException was unhandled
HResult=-2147024809
Message=Decimal byte array constructor requires an array of length four containing valid decimal bytes.
Source=mscorlib
StackTrace:
at System.Decimal.SetBits(Int32[] bits)
at RemObjects.SDK.BinSerializer.ReadDecimal(String name)
at TestCodeFirst.UserData.ReadComplex(Serializer serializer) in D:\Projects\Dot.Net\TestCodeFirstClient\TestCodeFirstClient\TestCodeFirst_Intf.cs:line 103
at RemObjects.SDK.Serializer.ReadComplexData(ComplexType value)
at RemObjects.SDK.Serializer.ReadComplex(String name, Type type)
at RemObjects.SDK.Serializer.Read(String name, Type type, StreamingFormat format)
at RemObjects.SDK.Message.Read(String name, Type type, StreamingFormat format)
at TestCodeFirst.Service1_Proxy.DoSomething(UserData s) in D:\Projects\Dot.Net\TestCodeFirstClient\TestCodeFirstClient\TestCodeFirst_Intf.cs:line 415
at TestCodeFirstClient.Form1.button1_Click(Object sender, EventArgs e) in D:\Projects\Dot.Net\TestCodeFirstClient\TestCodeFirstClient\Form1.cs:line 52
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at TestCodeFirstClient.Program.Main() in D:\Projects\Dot.Net\TestCodeFirstClient\TestCodeFirstClient\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

I can create a service method that returns a single decimal or an array of decimal with no problem. But I get the exception when it is a property of a RemObjects.SDK.Types.ComplexType

This is with VS 2015 update 2, latest production RemoteSDK using codefirst.

Thanks Mike

Strange. I can reproduce this error in your example, but I don’t have any problems with the decimal data-type in my prod. Service.

Hello

Could you show where exactly in your service/server the decimal type is used? Also is your server CodeFirst or RODL-based?

This is a code first server. I show where the decimal is set in the server in the first post,

[ServiceMethod, Description(“DoSomething returns UserData”)]
public UserData DoSomething(UserData s)
{
s.userID = “123”;
s.myEnum = MyEnum.Two;
s.hotelCodes = new string[2] { “Hotel1”, “Hotel2” };
s.decimalTest = 3.14M;
return s;
}

Sorry for confusing you. I meant @jensw_2000 's server. I already have a fix for this issue (it will be included into the next Beta). Still I wanted to double-check that it won’t break anything.

Any chance of getting a fix earlier so we can keep working?

Hi Anton,

yes, it is a CodeFirst Service. The decimal is working with 9.0 RTM and the current Beta Build.

Extracting a view lines of code isn’t so easy.

This is the type with the decimal property:

namespace InnovaSoft.PID.Shared.Types
{
    [System.Reflection.ObfuscationAttribute(Exclude = true)]
    public partial class PIDHLRCheckBalanceResult : ServiceResponse
    {
        public virtual decimal Balance { get; set; }
        public virtual string Unit { get; set; }
    }
}

Thhe base type “ServiceResponse”:

namespace InnovaSoft.PID.Shared.Types
{
    [ObfuscationAttribute(Exclude = true)]
    public class ServiceResponse : RemObjects.SDK.Types.ComplexType
    {
        #region Properties

        public String Description { get; set; } = "";
        public ServiceReturnCode ReturnCode { get; set; } = ServiceReturnCode.OK;
        public String ShortDesc { get; set; } = "";
        #endregion Properties

        #region Ctor

        /// <summary>
        /// Default OK Response
        /// </summary>
        public ServiceResponse()
        {
            ReturnCode = ServiceReturnCode.OK;
            ShortDesc = "OK";
            Description = "Der Methodenaufruf wurde fehlerfrei abgeschlossen";
        }

        /// <summary>
        /// Customizable Resoponse
        /// </summary>
        public ServiceResponse(ServiceReturnCode returnCode, string shortDesc, string description)
        {
            ReturnCode = returnCode;
            ShortDesc = shortDesc;
            Description = description;
        }

        #endregion Ctor
    }
}

This is the method, that does return the “PIDHLRCheckBalanceResult” type. It gets the return value over an interface by calling the LProvider.GetBalance() method:

    [ServiceMethod]
    public PIDHLRCheckBalanceResult GetHLRProviderBalance(Guid providerID)
    {
        using (var scope = Global.BeginLoggingLifetimeScope(MethodBase.GetCurrentMethod()))
        {
            var LProviders = scope.ResolveOptional<IEnumerable<IHLRProvider>>();
            var LProvider = LProviders.Where(pr => pr.ID == providerID).FirstOrDefault();
            if (LProviders != null)
            {
                return LProvider.GetBalance();
            }
            else
            {
                return new PIDHLRCheckBalanceResult()
                {
                    Balance = 0,
                    ReturnCode = ServiceReturnCode.ErrOperationFailed,
                    ShortDesc = "Provider nicht gefunden",
                    Description = "Es wurde kein Provider mit der ID '" + providerID + "' gefunden"
                };
            }
        }
    }

GetBalance() returns the PIDHLRCheckBalanceResult. This the relevant code part of this method, where the return code values will be set:

LResult.Balance = Convert.ToDecimal(result.Credits, new CultureInfo("en-US"));
LResult.ShortDesc = "OK";
LResult.Description = "";
LResult.ReturnCode = ServiceReturnCode.OK;

I’m calling this service method from two different clients. One ROSDK .Net client (it’s using the BinMessage) and one JSON client.

If all goes according tom plan, we’ll ship a new beta tomorrow (Wednesday)

Using the 4/20/2016 beta, the decimal problem is gone.

Thanks for the quick fix.

1 Like

RO 9.1.100.1259

There has been a regression.

The decimal error has returned.

“Message=Decimal byte array constructor requires an array of length four containing valid decimal bytes.”

Same issue with .1267

Hello.

Could you create a testcase? Pretty sure nothing was changed in this part that might cause a regression, so it must be something different.

Thanks in advance

Anton,

Need to send via email. Where should I send it?

Mike

Hello

support@ should work

Sent to support

Thanks for the testcase.

The Beta published yesterday already contains a fix for this issue (I got a similar testcase with a similar issue 2 days ago)

Regards

That fixed it. Thanks as usual for the fast response.

1 Like