Skip to content

Commit

Permalink
docs: Describe nuances between class vs interface service declarations (
Browse files Browse the repository at this point in the history
  • Loading branch information
meghanmae authored Aug 10, 2024
1 parent 5a5448f commit 82e335c
Showing 1 changed file with 32 additions and 9 deletions.
41 changes: 32 additions & 9 deletions docs/modeling/model-types/services.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

In a Coalesce application, you are likely to end up with a need for some API endpoints that aren't closely tied with your regular data model. While you could stick [Static Methods](/modeling/model-components/methods.md#static-methods) on one of your entities, to do so is detrimental to the organization of your code.

Instead, Coalesce allows you to generate API Controllers and a TypeScript client from a service. A service, in this case, is nothing more than a C# class or an interface with methods on it, annotated with `[Coalesce, Service]`. An implementation of this class or interface must be injectable from your application's service container, so a registration in Startup.cs is needed.
Instead, Coalesce allows you to generate API Controllers and a TypeScript client from a service. A service, in this case, is nothing more than a C# class or an interface with methods on it, annotated with `[Coalesce, Service]`. An implementation of this class or interface must be injectable from your application's service container, so a registration in Program.cs is needed.

The instance methods of these services work just like other custom [Methods](/modeling/model-components/methods.md) in Coalesce, with one notable distinction: Instance methods don't operate on an instance of a model, but instead on a dependency injected instance of the service.

Expand Down Expand Up @@ -44,21 +44,44 @@ public class WeatherService : IWeatherService
return response.Body.SerializeTo<WeatherData>();
}

public void MethodThatIsNotExposedBecauseItIsNotOnTheExposedInterface() { }
// This method is not exposed because it is not defined on the interface
public void MethodThatIsNotExposed() { }
}
```

And a registration:

``` c#
public class Startup
// In Program.cs
builder.Services.AddCoalesce<AppDbContext>();
builder.Services.AddScoped<IWeatherService, WeatherService>();
```

## Using Interfaces With Services
Interfaces annotated with `[Coalesce, Service]` will automatically expose all methods on that interface. Your interfaces should precisely define the service you intend to expose through Coalesce. Any members you do not want to expose should not be included in the interface.

Although it is not required to use an interface (you can generate endpoints directly from the implementation), it is highly recommended. Interfaces improve testability and reduce the risk of inadvertently changing the signature of a published API.

If you choose to generate directly from the implementation, annotate the class itself with `[Coalesce, Service]` rather than the interface. Unlike interfaces, each method you want to expose on the class must be explicitly annotated with the `[Coalesce]` attribute.

``` c#
[Coalesce, Service]
public class WeatherService
{
public void ConfigureServices(IServiceCollection services)
public WeatherService(AppDbContext db)
{
services.AddCoalesce<AppDbContext>();
services.AddScoped<IWeatherService, WeatherService>();
this.db = db;
}
}
```

While it isn't required that an interface for your service exist (you can generate directly from the implementation), it is highly recommended that an interface be used. Interfaces increase testability and reduce risk of accidentally changing the signature of a published API, among other benefits.
[Coalesce]
public WeatherData GetWeather(string zipCode)
{
// Assuming some magic HttpGet method that works as follows...
var response = HttpGet("http://www.example.com/api/weather/" + zipCode);
return response.Body.SerializeTo<WeatherData>();
}

// This method is not exposed because it lacks the [Coalesce] attribute
private void MethodThatIsNotExposed() { }
}
```

0 comments on commit 82e335c

Please sign in to comment.