# Business Object Proxies

{% hint style="warning" %}
As of version 16 the old BusinessFunctions are no longer usable. The recommended way of running server-side business logic is via the Business Object Proxies.
{% endhint %}

Starting with version 16 we added the possibility to run business object methods on the server-side, similar to what the old `BusinessFunctions` could do, with the addition of being able to run customized code as well, with each customization being specific to each server mandant.

{% hint style="info" %}
Enabling customizations for a server mandant can be done by editing the tlx.ini file where the server has been installed and adding a 'CustomPath' key with the value pointing to a custom path directory, just like we do to client mandants.

Example: `CustomPath = C:\Customizations\CustomServer16_Testing`
{% endhint %}

Invoking business logic on the server is straightforward, by using the newly added `TimeLine.Framework.Business.BusinessObjectProxy<T>` type. You can also use the non-generic version `TimeLine.Framework.Business.BusinessObjectProxy` type.

Here's an example of a simple business object that returns a simple hello world message:

```csharp
public class busHelloWorld : xObject
{
    protected busHelloWorld()
    {
    }

    public string SayHello(string name)
    {
        return "Hello world! My name is " + name;
    }
}
```

You can easily invoke the `SayHello` method on the server by creating a `Proxy` instance, as follows:

```csharp
var proxy = BusinessObjectProxy.Get<busHelloWorld>();
var messageFromServer = proxy.Invoke(x => x.SayHello("John Smith"));
xMessageBox.Show(messageFromServer);
```

Using the non-generic BusinessObjectProxy.Get(businessObjectId) method will allow you to invoke methods dynamically, like so:

```csharp
var proxy = BusinessObjectProxy.Get("busHelloWorld");
var messageFromServer = proxy.DynamicInvoke("SayHello", "John Smith");
xMessageBox.Show(messageFromServer);
```

{% hint style="info" %}
`DynamicInvoke` accepts the name or `ToString()` representation of a `MethodInfo` object as the method identifier and the following parameters are passed into the methods' arguments.
{% endhint %}

Dynamic invocation might be preferred when the caller does not *know* the called type.

The above code creates a `busHelloWorld` instance on the server and invoke the method with the parameters that were passed in from the client, before returning the result back to the client.&#x20;

Serialization is done automatically and supports all basic .NET Framework types (+ADO.NET) as well as `xDataSet`. You can also implement custom `Newtonsoft.Json` serializers for your custom data types.&#x20;

Both the dynamic and strongly typed invocation APIs have async variants and all APIs support passing in an optional `xTransaction` object that will be used when initializing the business object on the server-side. This way you can call multiple methods using the same transaction between these calls.

{% hint style="warning" %}
Business object methods that are to be called via the proxy should be designed with immutability in mind - each method call should receive all data it requires through it's parameters. State is not kept between proxy calls on the business object created on the server between methods.
{% endhint %}

Keep in mind that calling a method on a customized business object will require that both the client and the server point to the same customization (the customization will need to be deployed and updated on the server machine as well).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tldocs.gitbook.io/documentation/framework/server-side-logic-and-customization-v16+/business-object-proxies.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
