Defining Code-First services (.NET)
Supported data types
Not every .NET data type can be used in the interface published by the Code-First server.
Only following data types are supported:
RemObjects.SDK.Binary
(this is a wrapper over the System.IO.MemoryStream type)Boolean
andBoolean?
DateTime
andDateTime?
Decimal
andDecimal?
Double
andDouble?
Guid
andGuid?
Int32
andInt32?
Int64
andInt64?
String
. String values can be serialized and deserialized in 3 different incompatible encodings:- ANSI
- UTF8
- Unicode (compatible with the Delphi WideString data type)
System.Xml.XmlNode
Object.
List of supported value types of Object-typed parameters or properties is very limited:- null
- System.Boolean
- System.Byte
- System.SByte
- System.DateTime
- System.Decimal
- System.Double
- System.Int16
- System.Int32
- System.Int64
- System.String (serialized using the UTF8 encoding)
- System.Guid
Class inherited from RemObjects.SDK.ComplexType
. Public properties of classes inherited from RemObjects.SDK.ComplexType should have supported data types (including other ComplexType descendants)Enumeration
Arrays of supported data types
Service definitions
Sample Code-First service definition:
[Service]
public class SampleService : RemObjects.SDK.Server.Service
{
[ServiceMethod]
public string DoSomething(string someValue)
{
return "No Result";
}
}
[Service]
SampleService = public class(RemObjects.SDK.Server.Service)
public
[ServiceMethod]
method DoSomething(someValue: String): String;
end;
@Service open class SampleService : RemObjects.SDK.Server.Service {
@ServiceMethod
public func DoSomething(someValue: String!) -> String! {
return "No Result"
}
}
A class is considered as a Code-First service definition if these conditions are met:
- The class is inherited from the RemObjects.SDK.Server.Service class directly or indirectly
- The class is marked with the Service attribute
- The class is public
The method is considered as a published if these conditions are met:
- The method is public
- Method is marked with the ServiceMethod attribute
The following restrictions are applied to the published methods:
- Published method names should be unique
- Method result type (if any) and method parameter types should be ones of the supported types list
If these restrictions are not met the server app will be able to compile but will throw an exception at runtime. See the Debugging Cofe-First servers topic for advices on pinpointing such situations.
The following optional attributes can be applied to the service definition:
Attribute | Description |
---|---|
ServiceRequiresLogin | Sets the service instance's RequiresSession property to true at runtime. Service marked with this attribute will require user to first log in |
RemObjects.SDK.Server.ClassFactories.StandardClassFactory RemObjects.SDK.Server.ClassFactories.PerClientClassFactory RemObjects.SDK.Server.ClassFactories.SingletonClassFactor | Defines a class factory that will be used to instantiate the service instances to server the incoming requests. By default the Standart class factory is used |
Abstract | Marks the service as abstract. Abstract services are published in the server's RODL but cannot be called directly |
Documentation | Sets the documentation text for the service |
The required Service attribute has an optional Name parameter that can be used to alter the name that is used to publish the service:
[Service(Name = "NewServiceName")]
The following optional attributes can be applied to the service method definitions:
Attribute | Description |
---|---|
StreamAs | Sets encoding used to send string data. Can be applied to method or its parameters. When applied to the method - this attribute affects the method result serialization. This attribute is ignored for any non-string parameters |
Documentation | Sets the documentation text for the service method or its parameters. Can be applied to method or its parameters |
The required ServiceMethod attribute has an optional Name parameter that can be used to alter the name that is used to publish the service:
[ServiceMethod(Name = "NewMethodName")]
Asynchronous Service Methods
Starting with April 2021 releases Remoting SDK also provides support for service methods that use Task-based asynchronous pattern. This support is available for .NET Core, .NET 5+ and .NET Standard builds of Remoting SDK.
[Service]
public class SampleService : RemObjects.SDK.Server.Service
{
[ServiceMethod]
public async Task<string> DoSomething(string someValue)
{
var result = await ApiMethodAsync(someValue);
return result;
}
}
Asynchronous methods are represented in the server RODL similar to the usual synchronous methods and do not require client platforms to support Task-based asynchronicity.
Server-Sent Events definitions
Sample Server-Sent Events interface definition:
[EventSink]
public interface IChatEvents : IROEventSink
{
void MessageReceived(string sender, string message);
}
[EventSink]
IChatEvents = public interface(IROEventSink)
method MessageReceived(sender: String; message: String);
end;
@EventSink open protocol IChatEvents : IROEventSink {
func MessageReceived(_ sender: String!, _ message: String!)
}
An interface is considered as a Code-First Server-Sent Events interface definition if these conditions are met:
- The interface is inherited from the RemObjects.SDK.IROEventSink interface directly or indirectly
- The interface is marked with the EventSink attribute
- The interface is public
The following restrictions are applied to the published methods:
- Interface Method names should be unique
- Interface methods should not return any results (i.e their result type should be void).
- Interface method parameter types should be ones of the supported types list
The following optional attribute can be applied to the interface definition:
Attribute | Description |
---|---|
Documentation | Sets the documentation text for the events interface |
The required EventSink attribute has an optional Name parameter that can be used to alter the name that is used to publish the service:
[EventSink(Name = "NewEventsName")]
The following optional attributes can be applied to the interface method definitions:
Attribute | Description |
---|---|
StreamAs | Sets encoding used to send string data. Can be applied to method parameters. This attribute is ignored for non-string parameters |
Documentation | Sets the documentation text for the interface method or its parameters. Can be applied to method or its parameters |
Structure (complex type) definitions
Sample Code-First Structure definition:
public class SampleStructure : ComplexType
{
public string StringProperty { get; set; }
public int IntegerProperty { get; set; }
}
SampleStructure = public class(ComplexType)
public
property StringProperty: String read write;
property IntegerProperty: Integer read write;
end;
open class SampleStructure : ComplexType {
public var StringProperty: String!
public var IntegerProperty: Int32
}
A class is considered as a Code-First Structure definition if these conditions are met:
- The class is inherited from the RemObjects.SDK.Types.ComplexType class directly or indirectly
- The class or any of its ancestor classes is used as data type of a parameter in a service or event interface method, or as a data type of a Structure or an Exception property
- The class is public
The following restrictions are applied to the class properties:
- Indexed properties are not supported
- Parameter data types should be ones of the supported types list
The following optional attribute can be applied to the structure definition:
Attribute | Description |
---|---|
Documentation | Sets the documentation text for the structure |
The following optional attributes can be applied to the structure properties:
Attribute | Description |
---|---|
StreamAs | Sets encoding used to send string data. This attribute is ignored for non-string properties |
Documentation | Sets the documentation text for property |
Enumeration definitions
Sample Code-First enumeration definition:
public enum SampleEnum
{
First,
Second,
Third
}
SampleEnum = public enum (First, Second, Third);
open enum SampleEnum {
case First
case Second
case Third
}
An enum is considered as a valid Code-First Enum definition if these conditions are met:
- The enum element values start from 0 and are sequential. Enum with directly set element values (including Flag enums) are not supported
- The enum is used as data type of a parameter in a service or event interface method, or as a data type of a Structure or an Exception property
- The enum is public
The following optional attribute can be applied to the enum definition:
Attribute | Description |
---|---|
Documentation | Sets the documentation text for the enumeration definition |
The following optional attribute can be applied to the enum elements:
Attribute | Description |
---|---|
Documentation | Sets the documentation text for the enumeration element |
Exception definitions
Sample Code-First exception:
public class SampleException : ServerException
{
public string AdditionalData { get; set; }
}
SampleException = public class(ServerException)
public
property AdditionalData: String read write ;
end;
open class SampleException : ServerException {
public var AdditionalData: String!
}
A class is considered as a Code-First Exception definition if these conditions are met:
- The class is inherited from the RemObjects.SDK.Types.ServerException class directly or indirectly
- The class is public
The following restrictions are applied to the class properties:
- Indexed properties are not supported
- Parameter data types should be ones of the supported types list
The following optional attribute can be applied to the exception definition:
Attribute | Description |
---|---|
Documentation | Sets the documentation text for the exception |
The following optional attributes can be applied to the exception properties:
Attribute | Description |
---|---|
StreamAs | Sets encoding used to send string data. This attribute is ignored for non-string properties |
Documentation | Sets the documentation text for property |