REST Service Clients
Generates customizable C# clients for REST services that implement the service interfaces generated by the Service Contracts generator, and can be registered with the DI container as the implementation of those interfaces on the client side.
You can add your customizations to a subclass of a generated service client, and implement any additional logic for sending HTTP requests or handling HTTP responses as needed.
Since calling HTTP methods is asynchronous, the generator requires that service operations are defined as async
in the global model configuration global_config.xom
, as follows.
<svc:services-config async="true"
xmlns:svc="http://www.xomega.net/svc" />
You also need to make sure that you register a service with the DI that provides an instance of HttpClient
class configured with the base URI address for the REST API, as well as with any Authorization
or other headers set.
Generator inputs
The generator creates REST service clients for each service/object that has any operation annotated with a rest:method
configuration element, where you need to provide the verb
and a uri-template
that may contain input parameters in curly braces, as illustrated below.
<objects>
<object name="sales order">
<operations>
<operation name="update" type="update">
<input>
<param name="sales order id"/>
<struct name="data">[...]
</input>
<config>
<rest:method verb="PUT" uri-template="sales-order/{sales order id}"
xmlns:rest="http://www.xomega.net/rest"/>
</config>
</operation>
</operations>
</object>
</objects>
There can be only one input parameter that is not present in the URI template, which is usually a structure that goes into the body of the HTTP request.
For service operations that don't have a rest:method
configuration, the generator will output a warning to catch any mistakes in the model. If you intentionally don't want to expose a certain operation via REST, then you need to still add a rest:method
element with the not-supported="true"
attribute.
For example, the authenticate
operation below can be used by the Web API internally for the JWT authentication, but should not be exposed via REST, as shown below.
<objects>
<object name="person">
<operations>
<operation name="authenticate" type="update">
<input arg="credentials" struct="credentials"/>
<config>
<rest:method not-supported="true"/>
<wcf:operation not-supported="true"/>
</config>
</operation>
</operations>
</object>
</objects>
Whether the REST method is missing or not supported, the generated REST service proxies will still need to have the corresponding operation generated, which will throw a NotSupportedException
if called.
This REST configuration for standard CRUD, read list
and read enum
operations can be added automatically to the model by a special model enhancement CRUD generator with the Generate Rest Methods parameter set to true.
Generator outputs
This generator creates C# classes for service clients that call the REST services, as well as a static class for registering them for Dependency Injection (DI) with the service container, under the specified path for the client-side project.
For objects that have a rest:client
element under their config
element with a customize="true"
attribute, it also creates a subclass of the generated service client with a postfix Customized appended to the class name, if one does not exist yet, and will use this name for DI registration.
Configuration
The following sections describe the configuration parameters used by the generator.
Generator parameters
The following table lists configuration parameters that are set as the generator’s properties.
Parameter | Value Example | Description |
---|---|---|
Generator Name | REST Service Clients | The name of the current configuration of the generator that will appear in the model project and the build output. |
Folder Name | Presentation Layer\Common | Folder path to the generator inside the Model project. The folders are separated by a backslash (\). |
Include In Build | True | A flag indicating whether or not running this generator should be included in building of the model project. |
Output | ||
Output Path | ../MySolution.Client.Wpf /ServiceClients/{Module/}{File}.cs | Relative path where to output files with generated REST service clients. The path may contain {Module/} and {File} placeholders to output files by module and service respectively. |
Custom Path | Relative path where to output override classes for the generated service clients. If not set, then the OutputPath will be used. The path must contain a {File} placeholder to output files by service. | |
Registry File | ../MySolution.Client.Wpf /ServiceClients/RestClients.cs | Relative path to the file for service clients registration with the DI service container. The registration extension method will be derived from the file name. |
Model configuration
The model configuration parameters that are used by this generator consist of just the namespace for the service contracts, which is specified in the svc:services-config
element under the top-level config
model element, which is conventionally placed in the global_config.xom
file, as illustrated by the following snippet.
<svc:services-config namespace="MySolution.Services.Common" />
Common configurations
There is expected to be just one configuration of this generator in the model, with the parameter values as illustrated above.
How to use the generator
The sections below provide some details on how to work with the generator.
Running the generator
You can run this generator either for the entire model or for individual files by selecting them in the model project and running the generator from the context menu.
You can rerun the generator when you change or add operations with a REST configuration in the model.
Normally, this will require re-running other generators that depend on the same model elements, such as generators of UI views or service and data contracts as well as the service implementations. Therefore, this generator should be included in the build of the model project in the configuration, to allow you to easily regenerate all clients along with other artifacts.
Customizing the output
You should never edit generated service clients or the registration class directly. This allows re-running the generator at any time without losing your customizations.
To add your customizations, you should edit a subclass of the generated service client that was added when you specified the customize
attribute on the rest:client
element of the object's config
element, as follows.
<object name="sales order">
<operations>...</operations>
<config>
<rest:client customize="true"/>
</config>
</object>
You can also add your custom subclass of the generated client in your project, but then you will need to make sure to register that class with the dependency injection service container after the generated clients are registered.
Cleaning the generator’s output
This generator supports cleaning either all generated clients or only the ones from the selected model files using the Clean context menu for that generator.
Normally, cleaning the generated files makes sense if you are planning to change the output path for the generator, or when you have removed some of the services from the model, and want the generated classes deleted and removed from the target project.
The customization subclasses that were generated for the service clients with a customize="true"
attribute will not be cleaned during these operations to prevent any loss of custom code during an accidental run of such actions. Therefore, you may get compilation errors for those classes if you clean your service clients, and will need to delete them manually as needed.