[Guide] C# Programming Reference


Hello all! I have decided to make a small guide that covers special situations in the C# environment of FiveM. You’ll pick those up as you read through. Feel free to comment your own info.

1. Native / API Callbacks
Native or their API wrapping methods shouldn’t be executed in the constructor of a BaseScript derived class (this mostly applies to the client, although the exact behavior here is unknown).
A workaround for this limitation is to execute Function or API calls and any method that uses Function or API calls on the first tick:

public class TestScript : BaseScript
    #region Private Fields

    private bool firstTick = false;

    #region Initialization

    public TestScript()
        Tick += OnTick;

    #region Private Methods

    private async Task OnTick()
            firstTick = true;
            // API calls.

2. NUI Callbacks (Client)
API callbacks are tricky. Since the communication between NUI and the client are done in JavaScript, the returned data is already parsed and is pushed into ExpandoObject properties.

// ... Inside BaseScript
# NUI Implementation
private void RegisterNUICallback(string msg, Func<IDictionary<string, object>, CallbackDelegate, CallbackDelegate> callback)
    API.RegisterNuiCallbackType(msg); // Remember API calls must be executed on the first tick at the earliest!

    EventHandlers[$"__cfx_nui:{msg}"] += new Action<ExpandoObject, CallbackDelegate>((body, resultCallback) =>
        callback.Invoke(body, resultCallback);

I would understand if you’ll need a second to let it sink in. What we do here is listen to NUI events with a special event prefix: __cfx_nui:{eventName}. This is how FiveM framework does it so we have to obey. Now what is special are the passed arguments. They will ALWAYS be of type ExpandoObject and CallbackDelegate. The ExpandoObject is our data (google about the type and the DLR for more info). The ExpandoObject is of type IDictionary<string, object>, essentially keeping the data by <VariableName, VariableData>.
Essentially, our RegisterNUICallback command accepts a callback we call when the event is raised. So we just make life easier and pass it to the callback as IDictionary.

Note: I have yet to discover what does the second passed parameter (of type CallbackDelegate) is for. Please share if you can!

3. API RegisterCommand (Server)
This is yet another tricky command. RegisterCommand listens to commands typed in the remote console. The API function requests a string for the command name, a weird type of ‘InputArgument’ and a bool named restricted. The restricted is usually false, and the input argument is going to act as a delegate for us to execute when the command is passed. The question here is which arguments are passed with this callback. Appearantly these are <int, List. string> where int is source, List is really a list of parameter strings and the last string being the entire command.

// ... fyi: This function works in the constructor of the server BaseScript.
API.RegisterCommand("say", new Action<int, List<object>, string>((source, arguments, raw) =>
    foreach (var arg in arguments)
        Debug.WriteLine($"  {arg}");
}), false);

// Console command: say hello world!
// Debug:
// 0,
// say hello world!
//   hello
//   world!


Nice tut! thanks for this! :smiley:


Is API deprecated ? what is API exactly?


It doesnt look to be deprecated im currently working on a UI using these methods once i do proper testing and figure out how everything works i will post results


Great job with the tutorial.


what is API exactly?


ok to answer my own question, you should read the wiki carefully if you have the same problem :smiley: you have to get 2 seperate dlls and rename then as client and server. the one of the server has API and also other stuff i was missing.


Ok i have tried to send a message from NUI to C# to no avail i have tried everything i can think of using the guide provided and got nothing. If anyone could be so kind and actually show a fully working example it would be greatly appreciated or even just a better understanding on how to communicate back to C# from the NUI thanks


@dexslab, I’ve tried to figure it out too, and instead of playing with it much more, I just used a .lua file for the NUI callbacks. Temporary solution until can figure out the C# stuff.


Thanks for that i will still keep messing with it and figure it out from what i can see there has to be a way to do it the command is sent somewhere


After further testing i have found out how to use NUI callbacks it is very particular but it does work and you can definately communicate back and forth between the two i will attempt to write up a guide i am also thinking about making a C# template for people to use to make new scripts in C# so its easier then having to attempt to get it all set up it will just start a blank project with everything you need :smiley:


Thank you @Yuval for this guide.
But I have one question about it because I don’t have all understood. I need maybe a precise example to have an idea of how to use it in my case.

I already know how to send NUI messages, that’s ok, but now I would like my JavaScript event to be sent to C#.
With your example in “2. NUI Callbacks (Client)”, I’m able to be notified by the NUI by putting some code inside RegisterNUICallback().

My problem is that I don’t know how to use the callback. I would like to get something like in lua (I don’t want to use lua) :

RegisterNUICallback('YOUR_EVENT_NAME', function(data, cb)
    -- Do something here


And I guess you do it with the “body” ExpandoObject, but I can’t add a value to callback. I tried this without success :

dynamic response = new ExpandoObject();
response.openAdmin = false;
body = response;

Please could you tell me how to use this properly.
Thank you.


Looks like your using LUA, this script is for C#.

Look at https://github.com/Rene-Sackers/ui-mouse-example/blob/master/src/ui-mouse-example/client/client.lua

line 33 is what you are looking for!


The lua example @Ricardosan posted was to show what he wanted to convert into C# but is unable to do :wink:


Ah well then I’m in the same boat, trying to figure out how to use it in C#.