SapphireDb logo SapphireDb

Actions

SapphireDb comes with an alternative for controllers. They are called ActionHandler. You can use them like controllers in Asp.Net. You can define public methods that are exposed through the sapphire interfaces.

Basic example

Just create a class in your project and derive it from ActionHandlerBase.
You can use dependency injection in the constructor of the class.
The methods allow any serializable return type and you can also use async methods.
Calling the methods on client side is pretty easy. Just pass the name of the handler as first parameter and the name of the method as second.
Every other parameters will be used as parameters for the method.
\f:(csharp:ExampleActions.cs) public class ExampleActions : ActionHandlerBase\n {\n \tprivate readonly ExampleDb db;\n\n \tpublic ExampleActions(ExampleDb db)\n \t{\n \tthis.db = db;\n \t}\n\n \tpublic async Task<int> AsyncTask()\n \t{\n \t\tfor (int i = 0; i <= 100; i++)\n \t\t{\n \t\t\tThread.Sleep(10);\n \t\t}\n\n \t\treturn 33;\n \t}\n\n \tpublic string MethodWithParameters(string param1, string param2)\n \t{\n \t\treturn param1 + param2;\n \t}\n\n \tpublic void NoReturn()\n \t{\n \t\tConsole.WriteLine("This is a test");\n \t}\n } \f:(typescript:actions.component.ts) this.db.execute('example.MethodWithParameters', 'parameter1', 'parameter2')\n \t.subscribe(console.log);

Notifications

Because SapphireDb allows a bidirectional communication between client and server you can also send data during method execution. This is useful to transfer a state for example.
Use the Notify-method in your action handler to achieve that.
The client side can use the action helper to distinguish between notification and final result.
\f:(csharp:AsyncActions.cs) public class AsyncActions : ActionHandlerBase\n {\n \tpublic async Task<string> AsyncDelay()\n \t{\n \t\tfor (int i = 0; i <= 100; i++)\n \t\t{\n \t\t\tawait Task.Delay(10);\n \t\t\tNotify(i);\n \t\t}\n\n \t\treturn "complete";\n \t}\n } \f:(typescript:async-actions.component.ts) this.db.execute('example.MethodWithParameters', 'parameter1', 'parameter2')\n \t.subscribe(ActionHelper.result<string, number>(\n \t\t(result) => {\n \t\t\talert(result);\n \t\t},\n \t\t(notification) => {\n \t\t\tconsole.log(notification);\n \t\t}\n \t)\n );

Stream data from server

You can also stream async data from server to client.
\f:(csharp:AsyncActions.cs) public class AsyncActions : ActionHandlerBase\n {\n \tpublic async IAsyncEnumerable<string> AsyncEnumerableTest()\n \t{\n \t\tfor (int i = 0; i <= 100; i++)\n \t\t{\n \t\t\tyield return i.ToString();\n\n \t\t\tif (i % 10 == 0)\n \t\t\t{\n \t\t\t\tNotify("Progress: " + i + "%");\n \t\t\t}\n\n \t\t\tawait Task.Delay(10);\n \t\t}\n \t}\n } \f:(typescript:async-actions.component.ts) this.db.execute('example.AsyncEnumerableTest').subscribe(\n \tActionHelper.result(\n \t\t() => console.log('complete'),\n \t\t(value) => console.log(value),\n \t\t(notification) => console.warn(notification)\n \t));\n );\n\n // The code of the above example\n const result$ = this.db.execute<number, string>('example.AsyncEnumerableTest').pipe(\n \tshareReplay()\n );\n\n this.rangeValueStream$ = result$.pipe(\n \tfilter(v => v.type === ExecuteResponseType.Async),\n \tmap(v => v.result)\n );\n\n this.rangeValueStatus$ = result$.pipe(\n \tfilter(v => v.type === ExecuteResponseType.Notify),\n \tmap(v => v.notification)\n );

Stream data to server

Streaming data from client to server is also possible. It is also possible to do both.
\f:(csharp:AsyncActions.cs) public class AsyncActions : ActionHandlerBase\n {\n \tpublic async IAsyncEnumerable<string> StreamTest(IAsyncEnumerable<string> inputStream)\n \t{\n \t\tawait foreach (string input in inputStream)\n \t\t{\n \t\t\tyield return input + " from server";\n \t\t}\n \t}\n } \f:(typescript:async-actions.component.ts) const subject$ = new ReplaySubject<string>();\n this.streamValueResponse$ = this.db.execute<string>('example.StreamTest', subject$);\n subject$.next('value');\n subject$.complete();

This website uses Google Analytics. If you want to disable it just unselect the option: