Calling server actions (i.e. server code)
Why is it important? Real life example.
For example, you've got a certain component in your app, and a certain event in this component initiates client actions chain execution.
Thus, Save&Exit button for the onClick
event initiates the next validate, save, exit
chain. There are cases when after saving the
document you want to send an e-mail to certain users or call another server code. It means that your chain will look something like
that: validate, save, notify, exit
. It is important that the code is executed on the server and its execution is initiated from the
client. Of course, you can modify the DataController.ChangeData()
method or write your own controller, call it from the client
using fetch
, and process the response yourself. But first method is clearly defective, and the second one presumes routine manual coding.
In contrast, DWKit is a simple and unified mechanism of writing server methods in order to select their names from the drop-down list as
shown in the picture below.
DWKit server Action is a function receiving dynamic
and returning object
. I.e. it is the simplest type of server functions. And it is
most essential that DWKit can call such functions directly in the chain of actions which handle events from form components. But you can
always call them manually from any JavaScript code.
There are two types of action signature:
-
Synchronous action:
public object SyncAction(dynamic request)
{
...
} -
Asynchronous action:
public async Task<object> AsyncAction(dynamic request)
{
...
}
If synchronous methods are called in action, use synchronous actions. For asynchronous methods use asynchronous actions.
There is only one dynamic
parameter in Server Action. What this parameter contains depends on how this Server Action was called. There
are two types of calls: call from the chain of actions of event handlers and custom call. Server Action returns object, which is
interpreted in a definite way. Let's see how it happens.
Server Action call from the actions chain
If you have added server Action to IServerActionsProvider
implementation or in the CodeActions section in the admin panel, you can
immediately include it into event handlers of any component. See picture in the beginning of this section. When using this type of call the
server will receive as an input action parameter (dynamic request
) a ServerCodeActionRequest
object with the following properties:
public string FormName
- name of the form in events of which this action is called.public DynamicEntity Data
- form data.public dynamic Parameters
- parameters, with which client actions are called in the chain. See next picture.public string ModalId
- modal window identifier, filled if the action was called from a modal window.
Thus, if your server Action is called in the chain of client Actions, you can always work with the request
parameter as with an object
of the ServerCodeActionRequest
type. For example:
public object SyncAction(dynamic request)
{
var typedRequest = request as ServerCodeActionRequest;
var data = typedRequest.Data;
...
}
Server Action custom call
There are two functions in DWKit Global client API, using which you can call server Actions from any JavaScript code. For this use the following two functions. Full list of their parameters and using methods can be found here.
return callServerCodeAction(name, request, callback)
- returns delta for global state of the client application; it is used mainly inside another client action, which is called in the chain. It must be used withreturn
statement.callServerCodeActionDispatch(name, request, callback)
- immediately applies value returned from the server to the global state of the client application. Can be used in any JavaScript code.
Despite the fact that we've got two functions, parameters with which they are called are absolutely identical in use.
name
- name by which DWKit searches for Server Action.request
- is an object which will be transmitted to server Action as the(dynamic request)
parameter.
Let's see in more detail how request
object is transferred from the server to the client. Suppose you've got the following JavaScript
code:
someClientAction: function (args) {
var request = {
name: "Name",
value: 100
};
// return value style
return DWKitApp.API.callServerCodeAction("ServerActionName", request);
// OR
// immediate dispatch style
DWKitApp.API.callServerCodeActionDispatch("ServerActionName", request);
}
Then name
and value
values on the server can be received by the following method:
public object ServerActionName(dynamic request)
{
var name = request.name; // will be string "Name"
var value = request.value; // will be integer 100
return new {
...
};
}
Server Action returning value interpretation
Despite the fact that we've got two server Actions call types, their returning value is always interpreted by DWKit client-side in the same way. It means that returning value interpretation does not depend on the call type. Here are all possible methods to return values from server Action:
-
return null;
- means that action was completed successfully, there no changes to the client side of DWKit application. If server Action is called in the chain, the chain will be continued. -
throw new Exception(message);
- action will be completed with an error which will be displayed in the client as a pop-up message and stacktrace exception record in the browser console. If server Action is called in the chain, the chain will be interrupted. -
return new {...}
- returning an object of anonymous type; can be interpreted differently depending on whether hasstateDelta
anddata
properties.-
if there is a
stateDelta
property in the returning object, which is an object of anonymous type in itself, it will be applied to the global state of the client application. Actually you can manage client state from Server Actions the same way you do it via SignalR. For example, let's change inbox, total and outbox counts in the client:public object ServerActionName(dynamic request)
{
...
return new {
stateDelta = new {
app = new {
extra = new {
inbox = 40,
outbox = 10,
total = 50
}
}
}
};
} -
if there is a
data
property in the returning object which can be an object of anonymous type or aDynamicObject
object, it will be transmitted to further actions in the chain as adata
parameter. Below you will see an example of its use. Please note that if the Server Action is called outside the chain of actions, this value will be disregarded. -
if there are simultaneously
stateDelta
anddata
properties in the returning object, both mechanism described above will be applied. -
if there is neither
stateDelta
nordata
property in the returning object, returning value will be applied to the global state of the client application. I.e. the following code:public object ServerActionName(dynamic request)
{
...
return new {
app = new {
...
}
};
}will work similar to:
public object ServerActionName(dynamic request)
{
...
return new {
stateDelta = new {
app = new {
...
}
}
};
}
-
-
DynamicObject
object is returned. Usually it's form data. I.e. you can change form data in server Action called in the chain, which is launched upon event from the form component, and send them to the client. In further actions in the chain you can use changed data viadata
parameter, which is transmitted to each client action. For example, if after calling server Action there will besave
action in the chain (not necessarily straight away), changed data will be saved. Such code will look the following in the server:public object ServerActionName(dynamic request)
{
var typedRequest = request as ServerCodeActionRequest;
var data = typedRequest.Data;
data.amount = data.amount * 10; // increase document amount in ten times
return data;
}
CodeActionController behavior customization
Server Actions call and their parameters handling logic is in CodeActionController
. Here's its code
on GitHub.
You can see that the code is very simple and comprehensible. If you need complex behavior customization of the Server Actions mechanism,
just write your controller which will launch such actions and interpret input parameters and returning value.