# Servicestack
> slug: access-http-specific-features-in-services
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/access-http-specific-features-in-services.md
---
slug: access-http-specific-features-in-services
title: Access HTTP-specific Features in Services
---
ServiceStack is based on [http handlers](http://msdn.microsoft.com/en-us/library/system.web.ihttphandler.aspx), but ServiceStack provides a clean, dependency-free [IService](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/IService.cs) to implement your Web Services logic in. The philosophy behind this approach is that the less dependencies you have on your environment and its request context, the more testable and re-usable your services become.
::: info
The core [IRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IRequest.cs) and [IResponse](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IResponse.cs) interfaces used in filters and Services
:::
### Request Filters
The Request Filters are applied before the service gets called and accepts: (IRequest, IResponse, RequestDto) e.g:
```csharp
//Add a request filter to check if the user has a session initialized
this.RequestFilters.Add((httpReq, httpResponse, requestDto) =>
{
httpReq.Headers["HttpHeader"];
httpReq.QueryString["queryParam"];
httpReq.Form["htmlFormParam"];
httpReq.GetParam("aParamInAnyOfTheAbove");
httpReq.Cookies["requestCookie"];
httpReq.AbsoluteUri;
httpReq.Items["requestData"] = "Share data between Filters and Services";
//Access underlying Request in ASP.NET hosts
var aspNetRequest = httpResponse.OriginalRequest as HttpRequestBase;
//Access underlying Request in HttpListener hosts
var listenerRequest = httpResponse.OriginalRequest as HttpListenerRequest;
});
```
#### Services
When inheriting from Service you can access them via `base.Request` and `base.Response`:
```csharp
public class MyService : Service
{
public object Any(Request request)
{
var value = base.Request.GetParam("aParamInAnyHeadersFormOrQueryString");
base.Response.AddHeader("X-CustomHeader", "Modify HTTP Response in Service");
}
}
```
#### Response Filters
The Response Filters are applied after your service is called and accepts: (IRequest, IResponse, ResponseDto) e.g Add a response filter to add a 'Content-Disposition' header so browsers treat it as a native .csv file:
```csharp
this.ResponseFilters.Add((req, res, responseDto) =>
{
if (req.ResponseContentType == ContentType.Csv)
{
res.AddHeader(HttpHeaders.ContentDisposition,
$"attachment;filename={req.OperationName}.csv");
}
//Access underlying Response in ASP.NET hosts
var aspNetResponse = httpResponse.OriginalResponse as HttpResponseBase;
//Access underlying Response in HttpListener hosts
var listenerResponse = httpResponse.OriginalResponse as HttpListenerResponse;
});
```
### Communicating throughout the Request Pipeline
The recommended way to pass additional metadata about the request is to use the `IRequest.Items` collection. E.g. you can change what Razor View template the response DTO gets rendered in with:
```csharp
httpReq.Items["Template"] = "_CustomLayout";
...
var preferredLayout = httpReq.Items["Template"];
```
## Advantages for having dependency-free services
If you don't need to access the HTTP specific features your services can be called by any non-HTTP endpoint, like from a [message queue](/messaging).
### Injecting the IRequest into your Service
Although working in a clean-room can be ideal from re-usability and testability point of view, you stand the chance of missing out a lot of the features present in HTTP.
Just like using built-in Funq IOC container, the way to tell ServiceStack to inject the request context is by implementing the [IRequiresRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IRequiresRequest.cs) interface which will get the [IRequest](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Interfaces/Web/IRequest.cs) injected before each request.
::: info
ServiceStack's Convenient `Service` base class already implements `IRequiresRequest` which allows you to access the `IRequest` with `base.Request` and the HTTP Response with `base.Response`
:::
::: info
To return a customized HTTP Response, e.g. set Response Cookies or Headers, return the [HttpResult](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/HttpResult.cs) object
:::
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/add-servicestack-reference.md
---
slug: add-servicestack-reference
title: Add ServiceStack Reference
---
ServiceStack's **Add ServiceStack Reference** feature allows adding generated Native Types for the most popular typed languages and client platforms directly from within most major IDE's starting with [ServiceStackVS](/create-your-first-webservice#step-1-download-and-install-servicestackvs) - providing a simpler, cleaner and more versatile alternative to WCF's legacy **Add Service Reference** feature built into VS.NET.
Add ServiceStack Reference now supports
[C#](/csharp-add-servicestack-reference),
[TypeScript](/typescript-add-servicestack-reference),
[JavaScript](/javascript-add-servicestack-reference),
[Python](/python-add-servicestack-reference),
[PHP](/php-add-servicestack-reference),
[Swift](/swift-add-servicestack-reference),
[Java](/java-add-servicestack-reference),
[Kotlin](/kotlin-add-servicestack-reference),
[Dart](/dart-add-servicestack-reference),
[F#](/fsharp-add-servicestack-reference),
[VB.NET](/vbnet-add-servicestack-reference) and
[ES3 Common.js](/commonjs-add-servicestack-reference) including integration with most leading IDE's to provide a flexible alternative than sharing your DTO assembly with clients. Clients can now easily add a reference to a remote ServiceStack url and update DTOs directly from within VS.NET, Xamarin Studio, Xcode, Android Studio, IntelliJ and Eclipse. We plan on expanding on this foundation into adding seamless, typed, end-to-end integration with other languages - Add a [feature request for your favorite language](https://servicestack.net/ideas) to prioritize support for it sooner!
Native Types provides an alternative for sharing DTO dlls, that can enable a better dev workflow for external clients who are now able to generate (and update) Typed APIs for your Services from a single remote url directly within their favorite IDE - reducing the burden and effort required to consume ServiceStack Services whilst benefiting from clients native language strong-typing feedback.
### Supported Languages

### IDE Integration
To provide a seamless Development Experience, Add ServiceStack Reference is available as a plugin in most major IDEs which will allow your API Consumers to
be able easily add a typed Service Reference to your Services with just its URL in their preferred language from within JetBrains Rider, VS.NET, Android Studio, PyCharm, IntelliJ IDEA, RubyMine, PhpStorm, WebStorm and Eclipse:
[](https://www.youtube.com/watch?v=JKsgrstNnYY)
Here's a quick walk through installing the **ServiceStack** plugin and using it to add a remote ServiceStack Reference in a new C# Application:
:::tip
VSCode and other IDEs will be able to use the [Simple Command Line Utility](#simple-command-line-utilities) to add and update multiple Services references with a single command.
:::
### Call ServiceStack APIs from a Flutter App with native Dart client and DTOs
Walk through showing how you can use ServiceStack's Dart client library with your Flutter Android application to quickly get up and running with Add ServiceStack Reference.
### C# Xamarin.Android Example in VS.NET
Using C# to develop native Mobile and Desktop Apps provides a number of benefits including maximum reuse of your investments across multiple Client Apps where they're able to reuse shared functionality, libraries, knowledge, development workflow and environment in both Client and Server Apps.
### Call ServiceStack APIs from Python
This video tutorial looks at how we can leverage Add ServiceStack Reference for Python in PyCharm, VSCode and [Python Jupyter Notebooks](/jupyter-notebooks-python).
### Call ServiceStack APIs from PHP
This video tutorial looks at how we can easily integrate .NET Typed APIs to extend popular PHP Applications like Wordpress, Drupal or Laravel with [PHP Add ServiceStack Reference](/php-add-servicestack-reference).
### Instant Client Apps
[Instant Client Apps](https://apps.servicestack.net/) is a free tool to jump start your native client application development using a wide range of languages and platforms including: C#, NodeJS, Dart, Java, Kotlin, Swift, VB .NET and F#:
## gRPC
[ServiceStack gRPC](/grpc/) enables a highly productive development environment for developing high-performance gRPC HTTP/2 Services by making ServiceStack's existing typed Services available from ASP.NET's gRPC endpoints where ServiceStack offers a simplified development model for gRPC Clients for streamlined end-to-end productivity.
## C# Mobile and Desktop Apps
[](https://github.com/ServiceStackApps/HelloMobile)
The generated DTOs provides a highly productive development workflow and enables a succinct end-to-end Typed API that can be used in both **.NET Framework** and **.NET Standard 2.0** [Generic Service Clients](/csharp-client) to facilitate Rapid Development in .NET's most popular Mobile and Desktop platforms:
- WPF
- UWP
- Xamarin.Android
- Xamarin.iOS
- Xamarin.OSX
- Xamarin.Forms
- iOS
- Android
- UWP
The [HelloMobile](https://github.com/ServiceStackApps/HelloMobile) project contains multiple versions of the same App in all the above platforms demonstrating a number of different calling conventions, service integrations and reuse possibilities.
ServiceStack also allows for the maximum reuse possible by letting you reuse the same POCO DTOs used to define the Services contract with, in Clients Apps to provide its end-to-end typed API without any additional custom build tools, code-gen or any other artificial machinery, using just the DTOs in the shared `ServiceModel.dll` with any of the available highly performant [.NET generic Service Clients](/csharp-client) that be design encourages development of [resilient message-based Services](/what-is-a-message-based-web-service) for enabling [highly decoupled](/service-gateway) and easily [substitutable and mockable](/csharp-client#built-in-clients) Service Integrations.
## Utilize Native SDKs and Languages
Add ServiceStack Reference lets you utilize the native SDK's and development environment whilst maintaining the same productive development experience made possible with native idiomatic Service Clients in Web and across the most popular Mobile and Desktop platforms. App Developers can generate Typed DTOs for any ServiceStack Service in Android Apps using either [Java](/java-add-servicestack-reference) and [Kotlin](/kotlin-add-servicestack-reference), or use the [Swift](/swift-add-servicestack-reference) for development of native iOS or OSX Apps or [TypeScript](/typescript-add-servicestack-reference) for calling Services from [React Native, Node.js or Web Apps](https://github.com/ServiceStackApps/typescript-server-events).
### Flexible Customizations
Options for the generated DTOs can be further customized by updating the commented section in the header of the file. Each language will have different options for leveraging features native to each Language. See the specific language documentation for details on available options:
* [C# Options](/csharp-add-servicestack-reference#change-default-server-configuration)
* [TypeScript Options](./typescript-add-servicestack-reference.md#customize-dto-type-generation)
* [JavaScript Options](./javascript-add-servicestack-reference.md#customize-dto-type-generation)
* [Python Options](./python-add-servicestack-reference.md#customize-dto-type-generation)
* [Swift Options](/swift-add-servicestack-reference#swift-configuration)
* [Java Options](/java-add-servicestack-reference#java-configuration)
* [Kotlin Options](/kotlin-add-servicestack-reference#kotlin-configuration)
* [Dart Options](/dart-add-servicestack-reference#change-default-server-configuration)
* [F# Options](/fsharp-add-servicestack-reference#change-default-server-configuration)
* [VB.Net Options](/vbnet-add-servicestack-reference)
## Simple command-line utilities
The [x dotnet tool](/dotnet-tool) provides simple command-line utilities to easily Add and Update ServiceStack References for all of ServiceStack's supported languages.
## Installation
:::sh
dotnet tool install --global x
:::
::include npx-get-dtos.md::
This will make the following utilities available from your command-line which will let you download the Server DTO classes for a remote ServiceStack endpoint in your chosen language which you can use with ServiceStack's generic Service clients to be able to make end-to-end API calls.
Script
Alias
Language
x csharp
x cs
C#
x typescript
x ts
TypeScript
x mjs
JavaScript
x python
x py
Python
x java
Java
x kotlin
x kt
Kotlin
x swift
Swift
x dart
Dart
x vbnet
x vb
VB.NET
x fsharp
x fs
F#
## Usage
We'll walkthrough an example using TypeScript to download Server Types from the [techstacks.io](https://techstacks.io) ServiceStack Website to see how this works:
### Adding a ServiceStack Reference
To Add a TypeScript ServiceStack Reference just call `x typescript` with the URL of
a remote ServiceStack instance:
:::sh
x typescript https://techstacks.io
:::
Result:
```
Saved to: dtos.ts
```
Calling `x typescript` with just a URL will save the DTOs using the Host name, you can override this by specifying a FileName as the 2nd argument:
:::sh
x typescript https://techstacks.io Tech
:::
Result:
```
Saved to: Tech.dtos.ts
```
### Updating a ServiceStack Reference
To Update an existing ServiceStack Reference, call `x typescript` with the Filename:
:::sh
x typescript dtos.ts
:::
Result:
```
Updated: dtos.ts
```
Which will update the File with the latest TypeScript Server DTOs from [techstacks.io](https://techstacks.io). You can also customize how DTOs are generated by uncommenting the [TypeScript DTO Customization Options](/typescript-add-servicestack-reference#dto-customization-options) and updating them again.
#### Updating all TypeScript DTOs
Calling `x typescript` without any arguments will update **all TypeScript DTOs** in the current directory:
:::sh
x typescript
:::
Result:
```
Updated: Tech.dtos.ts
Updated: dtos.ts
```
To make it more wrist-friendly you can also use the shorter `x ts` alias instead of `x typescript`.
### Installing Generic Service Client
Now we have our TechStacks Server DTOs we can use them with the generic `JsonServiceClient` in the [@servicestack/client](https://www.npmjs.com/package/@servicestack/client) npm package to make Typed API Calls.
:::sh
npm install @servicestack/client
:::
#### TechStacks Example
Once installed create a `demo.ts` file with the example below using both the `JsonServiceClient` from the **@servicestack/client** npm package and the Server DTOs we
want to use from our local `dtos.ts` above:
```ts
import { JsonServiceClient } from '@servicestack/client';
import { GetTechnology, GetTechnologyResponse } from './dtos';
var client = new JsonServiceClient("https://techstacks.io")
async function main() {
let request = new GetTechnology()
request.Slug = "ServiceStack"
const response = await client.get(request)
console.log(response.Technology.VendorUrl)
}
main()
```
The `JsonServiceClient` is populated with the **BaseUrl** of the remote ServiceStack instance we wish to call. Once initialized we can send populated Request DTOs and handle
the Typed Response DTOs in Promise callbacks.
To run our TypeScript example we just need to compile it with TypeScript:
:::sh
tsc demo.ts
:::
Which will generate the compiled `demo.js` (and `typescript.dtos.js`) which we can then run with node:
:::sh
node demo.js
:::
Result:
```
https://servicestack.net
```
#### [Invoke ServiceStack APIs from the command-line](/post-command)
Easily inspect and invoke C# .NET Web APIs from the command-line with Post Command which allows you to both inspect and
call any ServiceStack API with just its name and a JS Object literal. API Responses returned in human-friendly markdown tables by default or
optionally as JSON & raw HTTP.
### Built in Authentication
One of the benefits of utilizing smart generic Service Clients is being able to embed high-level generic functionality like
Authentication that would be tedious and error prone for all API Consumers to have to implement manually.
All smart generic Service Clients have support for most of [built-in Authentication](/auth/authentication-and-authorization) options
including [OAuth Providers](https://github.com/ServiceStackApps/AndroidJavaChat) and [Sign In with Apple](/auth/signin-with-apple)
that are able to take advantage of the integrated and transparent JWT and Refresh Token Cookie support.
### Refresh Token Cookies supported in all Service Clients
::include jwt-service-clients.md::
### Integrate with Visual Studio
You can also easily integrate this within your VS.NET dev workflows by [adding it as an External Tool](https://docs.microsoft.com/en-us/visualstudio/ide/managing-external-tools?view=vs-2019) in the **External Tools** dialog box by choosing `Tools > External Tools`:

| ||
|-|-|
| Title | Update TypeScript &Reference |
| Command | web.exe |
| Arguments | ts |
| Initial directory | $(ProjectDir) |
| ||
Which will then let you update all your `*dtos.ts` TypeScript References in your project by clicking on `Tools > Update TypeScript Reference`
or using the `ALT+T R` keyboard shortcut.
If you wanted to Update your `*dtos.cs` **C# ServiceStack References** instead, just change Arguments to `cs`:

| ||
|-|-|
| **Title** | Update C# &Reference |
| **Command** | web.exe |
| **Arguments** | cs |
| **Initial directory** | $(ProjectDir) |
| ||
Refer to the [x usage output](#usage) above for the arguments or aliases for all other supported languages.
### Integrate with Rider
Just like with VS.NET above you can [add an External Tool](https://www.jetbrains.com/help/rider/Settings_Tools_External_Tools.html)
in [JetBrains Rider](https://www.jetbrains.com/rider/) by opening the Settings dialog with `CTRL+ALT+S` then searching for `external tools`
under the **Tools** category:

| ||
|-|-|
| **Name** | Update TypeScript Reference |
| **Command** | web.exe |
| **Arguments** | ts |
| **Working directory** | $FileParentDir$ |
| ||
Now you can update your `*dtos.ts` TypeScript References in your project by clicking on `External Tools > Update TypeScript Reference`
in the right-click context menu:

If you're updating references frequently you can save time by [assigning it a keyboard shortcut](https://www.jetbrains.com/help/rider/Configuring_Keyboard_and_Mouse_Shortcuts.html).
## Multiple File Upload Support with API Requests supported in all languages
To be able to call [AI Server](/ai-server/) APIs requiring file uploads we've added multiple file upload support with API Requests to the generic service clients for all our supported languages.
Here's what that looks like for different languages calling AI Server's `SpeechToText` API:
### C# Speech to Text
```csharp
using var fsAudio = File.OpenRead("audio.wav");
var response = client.PostFileWithRequest(new SpeechToText(),
new UploadFile("audio.wav", fsAudio, "audio"));
```
### Dart Speech to Text
```dart
var audioFile = new File('audio.wav');
var uploadFile = new UploadFile(
fieldName: 'audio',
fileName: audioFile.uri.pathSegments.last,
contentType: 'audio/wav',
contents: await audioFile.readAsBytes()
);
var response = await client.postFileWithRequest(new SpeechToText(), uploadFile);
```
### Python Speech to Text
```python
with open("files/audio.wav", "rb") as audio:
response = client.post_file_with_request(SpeechToText(),
UploadFile(field_name="audio", file_name="audio.wav", content_type="audio/wav", stream=audio))
```
### PHP Speech to Text
```php
$audioFile = __DIR__ . '/files/audio.wav';
/** @var GenerationResponse $response */
$response = $client->postFileWithRequest(new SpeechToText(),
new UploadFile(
filePath: $audioFile,
fileName: 'audio.wav',
fieldName: 'audio',
contentType: 'audio/wav'
));
```
### Swift Speech to Text
```swift
guard let audioURL = Bundle.module.url(forResource: "audio.wav", withExtension: nil) else {
return
}
let audioData = try Data(contentsOf: audioURL)
let response: TextGenerationResponse = try await client.postFileWithRequestAsync(
request:SpeechToText(),
file:UploadFile(fileName: "audio.wav", data:audioData, fieldName:"audio"))
```
### Kotlin Speech to Text
```kotlin
val audioBytes = Files.readAllBytes(Paths.get("audio.wav"))
val response = client.postFileWithRequest(SpeechToText(),
UploadFile("audio", "audio.wav", "audio/wav", audioBytes))
```
### Java Speech to Text
```java
byte[] audioBytes = Files.readAllBytes(Paths.get("audio.wav"));
var response = client.postFileWithRequest(request,
new UploadFile("audio", "audio.wav", "audio/wav", audioBytes));
```
### TypeScript Speech to Text
```js
// Create FormData and append the file
const formData = new FormData()
const audioFile = fs.readFileSync('audio.wav')
const blob = new Blob([audioFile], { type: 'audio/wav' })
// Explicitly set the field name as 'audio'
formData.append('audio', blob, 'audio.wav')
const api = await client.apiForm(new SpeechToText(), formData)
```
### Multiple File Uploads
All languages also support a `postFilesWithRequest` variant for uploading multiple files with an API Request.
E.g. here's an example of using `PostFilesWithRequest` to generate a video with a Watermark:
### C# Watermark Video
```csharp
using var fsVideo = File.OpenRead("video.mp4");
using var fsWatermark = File.OpenRead("watermark.png");
var response = client.PostFilesWithRequest(new QueueWatermarkVideo {
Position = WatermarkPosition.BottomRight
}, [
new UploadFile("video.mp4", fsVideo, "video"),
new UploadFile("watermark.png", fsWatermark, "watermark")
]);
```
## Advantages over WCF
- **Simple** Server provides DTOs based on metadata and options provided. No heavy client side tools, just a HTTP request!
- **Versatile** Clean DTOs works in all JSON, XML, JSV, MsgPack and ProtoBuf [generic service clients](/csharp-client#built-in-clients)
- **Reusable** Generated DTOs are not coupled to any endpoint or format. Defaults are both partial and virtual for maximum re-use
- **Resilient** Messaging-based services offer a number of [advantages over RPC Services](/advantages-of-message-based-web-services)
- **Flexible** DTO generation is customizable, Server and Clients can override built-in defaults
- **Integrated** Rich Service metadata annotated on DTO's, [Internal Services](/auth/restricting-services) are excluded when accessed externally
## In Contrast with WCF's Add Service Reference
WCF's **Add Service Reference** also allows generating a typed client from a single url, and whilst it's a great idea, the complexity upon what it's built-on and the friction it imposes were the primary reasons we actively avoided using it (pre-ServiceStack). We instead opted to reuse our server DTO types and created Generic WCF Proxies, to provide a cleaner and simpler solution when consuming our own WCF services.
## ServiceStack's Native Types Feature
As with any ServiceStack feature one of our primary goals is to [minimize unnecessary complexity](/autoquery#why-not-complexity) by opting for approaches that yield maximum value and minimal complexity, favoring re-use and simple easy to reason about solutions over opaque heavy black-box tools.
We can already see from the WCF scenario how ServiceStack already benefits from its message-based design, where as it's able to reuse any [Generic Service Client](/clients-overview), only application-specific DTO's ever need to be generated, resulting in a much cleaner, simpler and friction-less solution.
Code-first is another approach that lends itself to simpler solutions, which saves the effort and inertia from adapting to interim schemas/specs, often with impedance mismatches and reduced/abstract functionality. In ServiceStack your code-first DTOs are the master authority where all other features are projected off.
C# also has great language support for defining POCO Data Models, that's as terse as a DSL but benefits from great IDE support and minimal boilerplate, e.g:
```csharp
[Route("/path")]
public class Request : IReturn
{
public int Id { get; set; }
public string Name { get; set; }
...
}
```
Starting from a C# model, whilst naturally a better programmatic fit also ends up being richer and more expressive than XSD's which supports additional metadata annotations like Attributes and Interfaces.
### Remove Native Types Feature
Native Types is enabled by default in ServiceStack projects. It can be disabled by removing the `NativeTypesFeature` plugin:
```csharp
Plugins.RemoveAll(x => x is NativeTypesFeature);
```
### Excluding Types from Add ServiceStack Reference
To remove a type from the metadata and code generation you can annotate Request DTOs with `[ExcludeMetadata]`, e.g:
```csharp
[ExcludeMetadata]
public class ExcludedFromMetadata
{
public int Id { get; set; }
}
```
An alternative is it add it to the `IgnoreTypes` collection in the NativeTypes Feature Metadata Config in your AppHost:
```csharp
var nativeTypes = this.GetPlugin();
nativeTypes.MetadataTypesConfig.IgnoreTypes.Add(typeof(TypeToIgnore));
```
If you only want to limit code generation based on where the reference is being added from you can use the
[Restrict Attribute](/auth/restricting-services),
E.g you can limit types to only appear when the reference is added from localhost:
```csharp
[Restrict(LocalhostOnly = true)]
public class RestrictedToLocalhost { }
```
Or when added from within an internal network:
```csharp
[Restrict(InternalOnly = true)]
public class RestrictedToInternalNetwork { }
```
There's also the rarer option when you only want a service accessible from external requests with:
```csharp
[Restrict(ExternalOnly = true)]
public class RestrictedToExternalRequests { }
```
### Export Types
By default the `NativeTypeFeature` doesn't emit any **System** types built into the Base Class Libraries, these can be
emitted for non-.NET Languages with the new `ExportTypes` list, e.g. if your DTO's exposes the `DayOfWeek` System Enum it can
be exported by adding it to the pre-registered NativeTypesFeature's Plugin with:
```csharp
var nativeTypes = this.GetPlugin();
nativeTypes.MetadataTypesConfig.ExportTypes.Add(typeof(DayOfWeek));
```
If any of your DTO's has a `DayOfWeek` property it will emitted in the generated DTO's, Java example:
```java
public static enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday;
}
```
### Force Include Types in Native Types DTOs
ServiceStack's Add ServiceStack Reference feature carefully limits which DTOs it generates based on just the DTOs needed by different clients packages to call APIs. There's many reasons why Types aren't generated, e.g. they already exist in service client library, the APIs have [Visibility or Access restrictions](/auth/restricting-services), their built-in APIs purposefully hidden by ServiceStack to reduce bloat, etc.
We can override these rules for specific Types by including them in `Metadata.ForceInclude`, e.g:
```csharp
public override void Configure(Container container)
{
Metadata.ForceInclude = new() {
typeof(MetadataApp),
typeof(AppMetadata),
typeof(AdminQueryUsers),
typeof(AdminGetUser),
typeof(AdminCreateUser),
typeof(AdminUpdateUser),
typeof(AdminDeleteUser),
};
}
```
### Enable Versioning
You can implement our [recommended Versioning strategy](http://stackoverflow.com/a/12413091/85785)
and embed a version number to all generated Request DTOs by specifying an `AddImplicitVersion`,
either globally on the Server in your AppHost:
```csharp
var nativeTypes = this.GetPlugin();
nativeTypes.MetadataTypesConfig.AddImplicitVersion = 1;
```
Alternatively you can configure [AddImplicitVersion in client Options](/csharp-add-servicestack-reference#addimplicitversion).
### Generating Types from Metadata
Behind the scenes ServiceStack captures all metadata on your Services DTOs including Sub -classes, Routes, `IReturn` marker, C# Attributes, textual Description as well as desired configuration into a serializable object model accessible from `/types/metadata`:
## How it works
The Add ServiceStack Reference dialog just takes the URL provided and requests the appropriate route for the current project. Eg, for C#, the path used is at `/types/csharp`. The defaults are specified by the server and the resultant DTOs are saved and added the the project as `.dtos.`. The `Update ServiceStack Reference` menu is available when any file matches same naming convention of `.dtos.`. An update then looks at the comments at the top of the file and parses them to provide overrides when requesting new DTOs from the server. ServiceStackVS also watches these DTO files for updates, so just by saving them these files are updated from the server.
### Language Paths
| Path | Language |
| -- | -- |
| /types/csharp | C# |
| /types/typescript | TypeScript |
| /types/typescript.d | Ambient TypeScript Definitions |
| /types/js | CommonJS |
| /types/python | Python |
| /types/swift | Swift |
| /types/java | Java |
| /types/kotlin | Kotlin |
| /types/dart | Dart |
| /types/fsharp | F# |
| /types/vbnet | VB .NET |
| /types/metadata | Metadata |
::include add-servicestack-reference-footer.md::
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/adhoc-utils.md
---
slug: adhoc-utils
title: Adhoc Utils
---
## Image Utils
The `Image.ResizeToPng()` and `Image.CropToPng()` [extension methods](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/ImageExtensions.cs)
can be used to resize and crop `System.Drawing` Images, e.g:
```csharp
[AddHeader(ContentType = "image/png")]
public Stream Get(Resize request)
{
var imageFile = VirtualFiles.GetFile(request.Path);
if (imageFile == null)
throw HttpError.NotFound(request.Path + " was not found");
using (var stream = imageFile.OpenRead())
using (var img = Image.FromStream(stream))
{
return img.ResizeToPng(request.Width, request.Height);
}
}
[AddHeader(ContentType = "image/png")]
public Stream Get(Crop request)
{
var imageFile = VirtualFiles.GetFile(request.Path);
if (imageFile == null)
throw HttpError.NotFound(request.Path + " was not found");
using (var stream = imageFile.OpenRead())
using (var img = Image.FromStream(stream))
{
return img.CropToPng(request.Width, request.Height, request.StartX, request.StartY);
}
}
```
## Enum Utils
The `EnumUtils.GetValues()`, `IEnumerable.ToKeyValuePairs()` and `Enum.ToDescription()` extension methods
makes it easy to create data sources from Enums that can be annotated with `[ApiMember]` and `[Description]` attributes:
```csharp
List> Titles => EnumUtils.GetValues()
.Where(x => x != Title.Unspecified)
.ToKeyValuePairs();
List FilmGenres => EnumUtils.GetValues()
.Map(x => x.ToDescription());
```
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/auth/admin-apikeys.md
---
title: Simple Auth for .NET 10 Apps
---
With ServiceStack now fully [integrated with ASP.NET Identity Auth](/auth/identity-auth),
our latest [.NET 10 Tailwind Templates](/start) offer a full-featured Auth Configuration complete with User Registration,
Login, Password Recovery, Two Factory Auth, and more.
Whilst great for Web Applications that need it, it neglects the class of Apps which don't need User Auth and
the additional complexity it brings inc. Identity and Password Management, EF Migrations, Token Expirations, OAuth Integrations, etc.
For these stand-alone Apps, Microservices and Docker Appliances that would still like to restrict Access to their APIs
but don't need the complexity of ASP .NET Core's Authentication machinery, a simpler Auth Story would be preferred.
With the introduction of API Keys in this release we're able to provide a simpler Auth Story for .NET 10 Microservices
that's easy for **Admin** Users to manage and control which trusted clients and B2B Integrations can access their functionality.
:::youtube 0ceU91ZBhTQ
Simple Auth Story with API Keys ideal for .NET 10 Microservices
:::
The easiest way to get started is by creating a new Empty project with API Keys enabled with your preferred database to store the API Keys in. SQLite is a good choice for stand-alone Apps as it doesn't require any infrastructure dependencies.
Create a new Empty project with API Keys
### Existing Projects
Existing projects not configured with Authentication can enable this simple Auth configuration by running:
:::sh
npx add-in apikeys-auth
:::
Which will add the [ServiceStack.Server](https://nuget.org/packages/ServiceStack.Server) dependency and the [Modular Startup](/modular-startup) configuration below:
```csharp
public class ConfigureApiKeys : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices(services =>
{
services.AddPlugin(new AuthFeature([
new ApiKeyCredentialsProvider(),
new AuthSecretAuthProvider("p@55wOrd"),
]));
services.AddPlugin(new SessionFeature());
services.AddPlugin(new ApiKeysFeature
{
// Optional: Available Scopes Admin Users can assign to any API Key
// Features = [
// "Paid",
// "Tracking",
// ],
// Optional: Available Features Admin Users can assign to any API Key
// Scopes = [
// "todo:read",
// "todo:write",
// ],
});
})
.ConfigureAppHost(appHost =>
{
using var db = appHost.Resolve().Open();
var feature = appHost.GetPlugin();
feature.InitSchema(db);
});
}
```
Which configures the **AuthSecretAuthProvider** with the **Admin** password and **ApiKeysFeature** to enable [API Keys](/auth/apikeys) support.
### Admin UI
The **Admin** password will give you access to the [Admin UI](/admin-ui) at:
:::{.text-4xl .text-center .text-indigo-800}
/admin-ui
:::


### API Keys Admin UI
Clicking on **API Keys** menu item will take you to the API Keys Admin UI where you'll be able to create new API Keys
that you can distribute to different API consumers you want to be able to access your APIs:

The **ApiKeysFeature** plugin will let you control different parts of the UI, including what **Features** you want to
assign to API Keys and what **Scopes** you want individual API Keys to be able to have access to.
```csharp
services.AddPlugin(new ApiKeysFeature
{
Features = [
"Paid",
"Tracking",
],
Scopes = [
"todo:read",
"todo:write",
],
// ExpiresIn =[
// new("", "Never"),
// new("30", "30 days"),
// new("365", "365 days"),
// ],
// Hide = ["RestrictTo","Notes"],
});
```
Any configuration on the plugin will be reflected in the UI:

The API Keys Admin UI also lets you view and manage all API Keys in your App, including the ability to revoke API Keys,
extend their Expiration date as well as manage any Scopes and Features assigned to API Keys.

### Protect APIs with API Keys
You'll now be able to protect APIs by annotating Request DTOs with the `[ValidateApiKey]` attribute:
```csharp
[ValidateApiKey]
public class Hello : IGet, IReturn
{
public required string Name { get; set; }
}
```
Which only allows requests with a **valid API Key** to access the Service.
### Scopes
We can further restrict API access by assigning them a scope which will only allow access to Valid API Keys configured
with that scope, e.g:
```csharp
[ValidateApiKey("todo:read")]
public class QueryTodos : QueryDb
{
public long? Id { get; set; }
public List? Ids { get; set; }
public string? TextContains { get; set; }
}
[ValidateApiKey("todo:write")]
public class CreateTodo : ICreateDb, IReturn
{
[ValidateNotEmpty]
public required string Text { get; set; }
public bool IsFinished { get; set; }
}
[ValidateApiKey("todo:write")]
public class UpdateTodo : IUpdateDb, IReturn
{
public long Id { get; set; }
[ValidateNotEmpty]
public required string Text { get; set; }
public bool IsFinished { get; set; }
}
[ValidateApiKey("todo:write")]
public class DeleteTodos : IDeleteDb, IReturnVoid
{
public long? Id { get; set; }
public List? Ids { get; set; }
}
```
### Restrict To APIs
Scopes allow for coarse-grained access control allowing a single scope to access a logical group of APIs. For more
fine-grained control you can use **Restrict To APIs** to specify just the APIs an API Key can access:

Unlike scopes which can access APIs with the **same scope** or **without a scope**, Valid API Keys configured with
**Restrict To APIs** can only access those specific APIs.
### Features
Features are user-defined strings accessible within your Service implementation to provide different behavior
based on Features assigned to the API Key, e.g:
```csharp
public object Any(QueryTodos request)
{
if (Request.GetApiKey().HasFeature("Paid"))
{
//...
}
}
```
### Admin Only APIs
For APIs that should only be accessible to Admin Users (using AuthSecret) use `[ValidateIsAdmin]`, e.g:
```csharp
[ValidateIsAdmin]
public class AdminResetTodos : IPost, IReturnVoid {}
```
### API Explorer
Support for API Keys is also integrated into the [API Explorer](/api-explorer) allowing
users to use their API Keys to access API Key protected Services which are highlighted with a **Key** Icon:

Users can enter their API Key by clicking on the **Key** Icon in the top right, or the link in the Warning alert
when trying to access an API Key protected Service:

## API Keys and Admin Secret Credentials Auth Provider
The usability of Simple Admin API Keys is greatly improved with the `ApiKeyCredentialsProvider` which enables .NET Microservices to provide persistent UserSession-like behavior for API Keys and Admin Auth Secrets to enable a Credentials Auth implementation which users can use with their API Keys or Admin AuthSecret.
When registered a **Credentials** SignIn dialog will appear for [ServiceStack Built-in UIs](https://servicestack.net/auto-ui) allowing users to Sign In with their **API Keys** or Admin **Auth Secret**.

### Session Auth with API Keys
Behind the scenes this creates a Server [Auth Session](/auth/sessions)
but instead of maintaining an Authenticated User Session it saves the API Key in the session then attaches the API Key to each request. This makes it possible to make API Key validated requests with just a session cookie instead of requiring resubmission of API Keys for each request.
### Secure .NET Microservices and Docker Appliances
This is an ideal Auth Configuration for .NET Docker Appliances and Microservices like [AI Server](/ai-server/) that don't need the complexity of ASP .NET Core's Identity Auth machinery and just want to restrict access to their APIs with API Keys and restrict Admin functionality to Administrator's with an Auth Secret.
The benefit of `ApiKeyCredentialsProvider` is that it maintains a persistent Session so that end users
only need to enter their API Key a single time and they'll be able to navigate to all of AI Server's protected pages using their API Key maintained in their Server User Session without needing to re-enter it for each UI and every request.
### User Access with API Keys
AI Server uses **API Keys** to restrict Access to their AI Features to **authorized Users** with Valid API Keys who
are able to use its Built-in UIs for its AI Features with the Users preferred Name and issued API Key:

After signing in a single time they'll be able to navigate to any protected page and start using AI Server's AI features:

### User Access to API Explorer
This also lets users use their existing Auth Session across completely different UIs
like [API Explorer](/api-explorer)
where they'll have the same access to APIs as they would when calling APIs programatically with their API Keys, e.g:

## Admin Access
AI Server also maintains an Admin UI and Admin APIs that are only accessible to **Admin** users who
Authenticate with the App's configured Admin Auth Secret who are able to access AI Server's Admin
UIs to monitor Live AI Requests, create new User API Keys, Manage registered AI Providers, etc.

### Admin Restricted APIs
You can restrict APIs to Admin Users by using `[ValidateAuthSecret]`:
```csharp
[Tag(Tags.Admin)]
[ValidateAuthSecret]
[Api("Add an AI Provider to process AI Requests")]
public class CreateAiProvider : ICreateDb, IReturn
{
//...
}
```
Which are identified in API Explorer with a **padlock** icon whilst APIs restricted by API Key are
identified with a **key** icon:

### Client Usage
All HTTP and existing [Service Clients](https://docs.servicestack.net/clients-overview) can be configured to use API Keys
for machine-to-machine communication, which like most API Key implementations can be passed in a [HTTP Authorization Bearer Token](https://datatracker.ietf.org/doc/html/rfc6750#section-2.1)
that can be configured in Service Clients with:
#### C#
```csharp
var client = new JsonApiClient(BaseUrl) {
BearerToken = apiKey
};
```
#### TypeScript
```ts
const client = new JsonServiceClient(BaseUrl)
client.bearerToken = apiKey
```
### API Key HTTP Header
Alternatively, API Keys can also be passed in the `X-Api-Key` HTTP Header which allows clients to be configured
with an alternative Bearer Token allowing the same client to call both **Authenticated** and **API Key** protected APIs, e.g:
#### C#
```csharp
var client = new JsonApiClient(BaseUrl) {
BearerToken = AuthSecret,
Headers = {
[HttpHeaders.XApiKey] = apiKey
}
};
```
#### TypeScript
```ts
const client = new JsonServiceClient(BaseUrl)
client.bearerToken = AuthSecret
client.headers.set('X-Api-Key', apiKey)
```
## Development
You can avoid having to re-renter AuthSecret and API Keys during Development by populating every request with
the configured Admin AuthSecret which allows you to call both `[ValidateApiKey]` and `[ValidateIsAdmin]` protected APIs:
```csharp
#if DEBUG
PreRequestFilters.Add((req, res) =>
{
req.Items[Keywords.AuthSecret] = authSecret;
req.Items[Keywords.Authorization] = "Bearer " + authSecret;
});
#endif
```
### Summary
We hope this shows how stand-alone .NET 10 Microservices and self-contained Docker Apps can use the
simple **Admin** and **API Keys** configuration to easily secure their APIs, complete with **Management UI**
and **typed Service Client** integrations.
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/admin-ui-analytics.md
---
title: Admin UI Analytics for SQLite
---
Comprehensive API Analytics is available to all ServiceStack Apps configured with [SQLite Request Logging](/sqlite-request-logs).
:::youtube kjLcm1llC5Y
In Depth and Interactive API Analytics available to all ASP .NET Core ServiceStack Apps!
:::
### Benefits of API Analytics
They provide deep and invaluable insight into your System API Usage, device distribution, its Users, API Keys and the
IPs where most traffic generates:
- **Visibility:** Provides a clear, visual summary of complex log data, making it easier to understand API usage and performance at a glance.
- **Performance Monitoring:** Helps track key metrics like request volume and response times to ensure APIs are meeting performance expectations.
- **User Understanding:** Offers insights into how users (and bots) are interacting with the APIs (devices, browsers).
- **Troubleshooting:** Aids in quickly identifying trends, anomalies, or specific endpoints related to issues.
- **Resource Planning:** Understanding usage patterns helps in scaling infrastructure appropriately.
- **Security Insight:** Identifying bot traffic and unusual request patterns can be an early indicator of security concerns.
- **Interactive Analytics:** Analytics are also interactive where you're able to drill down to monitor the activity of individual APIs, Users, API Keys and IPs with links back to the request logs which the summary analytics are derived from.
### Getting Started
As they offer significant and valuable insights they're now built into all new ASP.NET Core IdentityAuth templates,
existing .NET 10 IdentityAuth templates can enable it with:
:::sh
npx add-in sqlitelogs
:::
.NET 10 Templates that are not configured to use [Endpoint Routing](/endpoint-routing)
and [ASP.NET Core IOC](/net-ioc) will need to explicitly register `SqliteRequestLogger`
as a singleton dependency in addition to configuring it on the `RequestLogsFeature` plugin:
```csharp
public class ConfigureRequestLogs : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices((context, services) =>
{
var logger = new SqliteRequestLogger();
services.AddSingleton(logger);
services.AddPlugin(new RequestLogsFeature {
RequestLogger = logger,
EnableRequestBodyTracking = true,
EnableErrorTracking = true
});
services.AddHostedService();
if (context.HostingEnvironment.IsDevelopment())
{
services.AddPlugin(new ProfilingFeature());
}
});
}
```
## Analytics Admin UI
Once configured, [SQLite Request Logs](/sqlite-request-logs) enable a more feature rich Request Logging Admin UI which utilizes the full queryability of an AutoQueryGrid to filter, sort and export Request Logs.
[](/img/pages/admin-ui/sqlitelogs.webp)
### Rolling Monthly Request Logs
Benefits of using SQLite includes removing load from your App's primary database and being able to create naturally scalable and isolated Monthly databases on-the-fly which allow requests to be easily archived into managed file storage instead of a singular growing database.
## Analytics Overview
It also enables the new **Analytics** Admin UI in the sidebar which initially displays the API Analytics overview Dashboard:
[](/img/pages/admin-ui/analytics-apis1.webp)
Different charts displayed on the dashboard include:
### Distribution Pie Charts
Lets you quickly understand the composition of your user base and traffic sources and the
distribution of users across different web browsers, device types, and to identify the proportion of traffic coming from automated bots.
### Requests per day Line Chart
Lets you monitor API usage trends and performance over time. It tracks the total number of API requests and the average response
time day-by-day. You can easily spot trends like peak usage hours/days, identify sudden spikes or drops in traffic,
and correlate request volume with API performance which is crucial for capacity planning and performance troubleshooting.
### API tag groups Pie Chart
Lets you understand the usage patterns across different functional categories of your APIs.
By grouping API requests based on assigned tags (like Security, Authentication, User Management, Tech, etc.), you get a
high-level view of which *types* of functionalities are most frequently used or are generating the most load.
### API Requests Bar Chart
Lets you identify the most and least frequently used specific API endpoints which ranks individual API endpoints by
the number of requests they receive. This helps pinpoint:
- **Critical Endpoints:** The most heavily used APIs that require robust performance and monitoring.
- **Optimization Targets:** High-traffic endpoints that could benefit from performance optimization.
- **Underutilized Endpoints:** APIs that might be candidates for deprecation or require promotion.
- **Troubleshooting:** If performance issues arise (seen in the line chart), this helps narrow down which specific endpoint might be responsible.
[](/img/pages/admin-ui/analytics-apis2.webp)
### Total Duration Bar Chart
Identifies which API endpoints consume the most *cumulative processing time* over the selected period.
Even if an API endpoint is relatively fast per call, if it's called extremely frequently, it can contribute significantly to overall server load.
Optimizing these can lead to significant savings in server resources (CPU, memory).
### Average Duration Bar Chart
Pinpoints which API endpoints are the slowest on a *per-request* basis. APIs at the top of this list are prime candidates
for performance investigation and optimization, as they represent potential user-facing slowness or system bottlenecks.
### Requests by Duration Ranges Histogram
Provides an overview of the performance distribution for *all* API requests.
This chart shows how many requests fall into different speed buckets and helps you understand the overall responsiveness of your API system at a glance.
## Individual API Analytics
Clicking on an API's bar chart displays a dedicated, detailed view of a single API endpoint's behavior, isolating its performance
and usage patterns from the overall system metrics offering immediate insight into the endpoint's traffic volume and reliability.
[](/img/pages/admin-ui/analytics-api.webp)
### Total Requests
Displays the total requests for an API during the selected month. It includes HTTP Status Breakdown which
provide **direct access to the filtered request logs**. This is a major benefit for **rapid troubleshooting**, allowing
you to instantly view the specific log entries corresponding to successful requests or particular error codes for this API.
### Last Request Information
Provides immediate context on the most recent activity for this endpoint with *when* the last request occurred,
the source **IP address** and device information to help understand recent usage and check if the endpoint is still active,
or quickly investigate the very last interaction if needed.
### Duration Summary Table (Total, Min, Max)
Quantifies the performance characteristics specifically for this endpoint with the cumulative (Total) processing load,
the best-case performance (Min), and the worst-case performance (Max) which is useful for identifying performance outliers.
### Duration Requests Histogram
Visualizes the performance distribution for this API.
### Top Users Bar Chart
Identifies which authenticated users are most frequently calling this API and relies on this endpoint the most.
This can be useful for identifying power users, potential API abuse by a specific user account, or understanding the impact of changes to this API on key users.
### Top IP Addresses Bar Chart
Shows which source IP addresses are generating the most traffic for this API.
Useful for identifying high-volume clients, specific servers interacting with this endpoint, or potentially malicious IPs.
## Users
The **Users** tab will display the top 100 Users who make the most API Requests and lets you click on a Users bar chart
to view their individual User analytics.
[](/img/pages/admin-ui/analytics-users.webp)
### Individual User Analytics
Provides a comprehensive view of a single user's complete interaction history and behavior across all APIs they've accessed,
shifting the focus from API performance to user experience and activity.
[](/img/pages/admin-ui/analytics-user.webp)
### User Info & Total Requests
Identifies the user and quantifies their overall activity level. Clicking on their ID or Name will navigate to the Users Admin UI.
It also shows their success/error rate via the clickable status code links. This helps gauge user engagement and baseline activity.
### Last Request Information
Offers a snapshot of the user's most recent interaction for immediate context.
Knowing **when**, **what** API they called, from which **IP address**, using which **client** & **device** is valuable
for support, identifying their last action or checking recent activity.
### HTTP Status Pie Chart
Visualizes the overall success and error rate specifically for this user's API requests.
### Performance & Request Body Summary Table
Quantifies the performance experienced by this user and the data they typically send.
### Duration Requests Histogram
Shows the distribution of response times for requests made by this user to help understand the typical performance this user experiences.
### Top APIs Bar Chart
Reveals which API endpoints this user interacts with most frequently and help understanding user behavior and which features they use most.
### Top IP Addresses Bar Chart
Identifies the primary network locations or devices the user connects from.
### User Admin UI Analytics
To assist in discoverability a snapshot of a Users Analytics is also visible in the Users Admin UI:
[](/img/pages/admin-ui/analytics-user-adminui.webp)
Clicking on **View User Analytics** takes you to the Users Analytics page to access to the full Analytics features and navigation.
## API Keys
The **API Keys** tab will display the top 100 API Keys who make the most API Requests and lets you click on an API Key
bar chart to view its individual API Key analytics.
[](/img/pages/admin-ui/analytics-apikeys.webp)
### Individual API Key Analytics
Provides comprehensive API Key analytics Similar to User Analytics but limited to the API Usage of a single API Key:
[](/img/pages/admin-ui/analytics-apikey.webp)
## IPs
The **IP Addresses** tab will display the top 100 IPs that make the most API Requests. Click on an IP's
bar chart to view its individual analytics made from that IP Address.
[](/img/pages/admin-ui/analytics-ips.webp)
### Individual IP Analytics
Provides comprehensive IP Address analytics Similar to User Analytics but limited to the API Usage from a single IP Address:
[](/img/pages/admin-ui/analytics-ip.webp)
## Blocking User Agents
The insights from the Analytics showed us that our [pvq.app](https://pvq.app) was experiencing significant load from
AI bots and scrapers which was the primary cause of its high resource usage and detrimental load times for normal
user requests, so much so we've intervened to prevent these bots from scraping our site.
### Disallowing Bots in robots.txt
In an ideal world you would just need to instruct problematic bots not to scrape your site by adding them to [pvq.app/robots.txt](https://pvq.app/robots.txt), e.g:
```txt
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
User-agent: bytespider
Disallow: /
User-agent: gptbot
Disallow: /
User-agent: claudebot
Disallow: /
User-agent: amazonbot
Disallow: /
User-agent: mj12bot
Disallow: /
User-agent: semrushbot
Disallow: /
User-agent: dotbot
Disallow: /
User-agent: WhatsApp Bot
Disallow: /
User-agent: *
Disallow: /
```
### Disallowing Bot Requests
As this was not having an immediate effect we took a more forceful approach to implement a middleware to reject all
requests from disallowed bots from accessing our App which you can add to your own App with:
:::sh
npx add-in useragent-blocking
:::
This will allow you to configure which Bot User Agents you want to reject from accessing your site, e.g:
```csharp
services.Configure(options =>
{
// Add user agents to block
options.BlockedUserAgents.AddRange([
"bytespider",
"gptbot",
"gptbot",
"claudebot",
"amazonbot",
"imagesiftbot",
"semrushbot",
"dotbot",
"semrushbot",
"dataforseobot",
"WhatsApp Bot",
"HeadlessChrome",
"PetalBot",
]);
// Optional: Customize the response status code
// options.BlockedStatusCode = StatusCodes.Status429TooManyRequests;
// Optional: Customize the blocked message
options.BlockedMessage = "This bot is not allowed to access our website";
});
```
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/admin-ui-database.md
---
title: Database Admin
---
The Database Admin UI lets you quickly browse and navigate your App's configured RDBMS schemas and tables:
It can be enabled by registering the `AdminDatabaseFeature` plugin from [ServiceStack.Server](https://nuget.org/packages/ServiceStack.Server):
```csharp
services.AddPlugin(new AdminDatabaseFeature());
```
Which without any additional configuration your App's configured databases will be listed on the home page, including their schemas, tables and any registered [named connections](/ormlite/getting-started#multiple-database-connections):

Selecting a table takes us to a familiar tabular search results grid, similar in appearance and functionality to [Locode's Auto UI](/locode/):

Whilst Locode gives you an entire Auto Management UI with all modifications performed through managed [AutoQuery APIs](/autoquery/), Database Admin instead focuses on providing a great readonly UX for querying & inspecting your App's data, starting with multiple views or quickly previewing every row in either **Pretty** JSON format:
Where it will also let you copy every row in JSON format, whilst the **Preview** tab shows a friendlier view of the row's fields:
The tabular grid is highly personalizable where it lets change the query preferences and display fields for each table, where they're persisted in localStorage and preserved across browser restarts:
Likewise so are the flexible filtering options allowing any number of filters per column:
The number and type of filters are readily available from the **Filters** dropdown showing all filters grouped under their column name where they're easily cleared per filter, column or using **Clear All** to clear all filters:

After you've finished customizing your table search view, you can export the data with the **Excel** button to download the results in [CSV Format](/csv-format) where it can be opened in your favorite spreadsheet, e.g:

Alternatively the **Copy URL** button can be used to generate the API data URL to return results in JSON:
## Database Admin Customizations
Some customizations is available on the `AdminDatabaseFeature` plugin where you can control the maximum size of resultsets returned and you can use the `DatabaseFilter` to control which databases and schemas are displayed as well as changing the labels shown by setting their `Alias` properties, e.g:
```csharp
Plugins.Add(new AdminDatabaseFeature {
QueryLimit = 100,
DatabasesFilter = dbs => {
foreach (var db in dbs)
{
if (db.Name == "main")
{
db.Alias = "Northwind";
db.Schemas[0].Alias = "Traders";
}
else if (db.Name == "chinook")
{
db.Alias = "Chinook";
db.Schemas[0].Alias = "Music";
}
}
},
});
```
## Feedback Welcome
We hope you'll find the Database Admin feature useful, please let us know what other features you would like in [ServiceStack/Discuss](https://github.com/ServiceStack/Discuss/discussions).
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/admin-ui-features.md
---
title: Admin UI Features
---
Built into ServiceStack v6+ Apps is the [Admin UI](/admin-ui) providing **Admin** Users a UX Friendly UI to access App features & summary insights from:
/admin-ui
Which after authenticating will take you to the Admin UI dashboard showing the authenticated Admin User details and general API stats:
Further Admin UI functionality can be enabled by adding the necessary dependencies and Admin APIs necessary to implement the Admin UI Features.
### Disabling the Admin UI
If desired, the **/admin-ui** features can be selectively or entirely disabled using the `AdminUi` Enum flags:
```csharp
ConfigurePlugin(feature => feature.AdminUi = AdminUi.None);
```
## Admin Users
User management functionality for creating & modifying users, assigning Roles & Permissions, locking users or updating their passwords can be enabled by registering `AdminUsersFeature` plugin:
```csharp
Plugins.Add(new AdminUsersFeature());
```
Which enables a familiar UI for searching & managing users:
::: info
See [Admin UI User Docs](/admin-ui-users) to learn about Admin User features and available customization options
:::
## Redis Admin
The [Redis Admin UI](/admin-ui-redis) lets you manage your App's configured Redis Server with a user-friendly UX for managing core Redis data types, simple search functionality to quickly find Redis values, quick navigation between related values, first class support for JSON values and a flexible command interface and command history to inspect all previously run redis commands.
It can be enabled by registering the `AdminRedisFeature` plugin:
```csharp
services.AddPlugin(new AdminRedisFeature());
```
Which will enable the **Redis** Admin UI:
[](/admin-ui-redis)
::: info
See [Redis Admin docs](/admin-ui-redis) for more info.
:::
## Database Admin
The [Database Admin UI](/admin-ui-database) lets you quickly browse and navigate your App's configured RDBMS schemas and tables:
It can be enabled by registering the `AdminDatabaseFeature` plugin from [ServiceStack.Server](https://nuget.org/packages/ServiceStack.Server):
```csharp
services.AddPlugin(new AdminDatabaseFeature());
```
Which will enable the **Database** Admin UI:
[](/admin-ui-database)
::: info
See [Database Admin docs](/admin-ui-database) for more info.
:::
## Request Logging & Profiling
Enables invaluable observability into your App, from being able to quickly inspect and browse incoming requests, to tracing their behavior:
:::sh
npx add-in profiling
:::
Which will add the [Modular Startup](/modular-startup) configuration to your Host project that registers both Request Logging & Profiling features when running your App in [DebugMode](/debugging#debugmode) (i.e. Development):
```csharp
[assembly: HostingStartup(typeof(MyApp.ConfigureProfiling))]
namespace MyApp;
public class ConfigureProfiling : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices((context, services) => {
if (context.HostingEnvironment.IsDevelopment())
{
services.AddPlugin(new ProfilingFeature
{
IncludeStackTrace = true,
});
}
});
}
```
Which will enable the Request Logging & Profiling UIs:
::: info
See [Admin Logging & Profiling UI docs](/admin-ui-profiling) to learn about Admin Profiling feature and available customization options.
:::
## Validation
The Admin Validation feature enables adding dynamically sourced validation rules that can be applied & modified at runtime.
The most popular `IValidationSource` for maintaining dynamic validation rules is `OrmLiteValidationSource` for maintaining them
in the App's registered database's `ValidationRule` RDBMS Table:
```csharp
[assembly: HostingStartup(typeof(MyApp.ConfigureValidation))]
namespace MyApp;
public class ConfigureValidation : IHostingStartup
{
// Add support for dynamically generated db rules
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices(services => services.AddSingleton(c =>
new OrmLiteValidationSource(c.Resolve(), HostContext.LocalCache)))
.ConfigureAppHost(appHost => {
// Create `ValidationRule` table if it doesn't exist in AppHost.Configure() or Modular Startup
appHost.Resolve().InitSchema();
});
}
```
Which can be quickly added to your project with:
:::sh
npx add-in validation-source
:::
Which the built-in [Validation Feature](/validation.html#validation-feature) detects to register the `GetValidationRules` and `ModifyValidationRules` APIs used by the Admin Validation Feature:
::: info
See [Admin UI Validation Docs](/admin-ui-validation) to learn about dynamic DB Validation Rules
:::
## Recommend Admin UI Features
The Admin UI was designed with room to grow. You can let us know what features you would find most valuable on our [GitHub Discussions](https://github.com/ServiceStack/Discuss/discussions/2).
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/admin-ui-identity-roles.md
---
title: Identity Roles & Claims UI
---
The Roles Admin UI is enabled when registering the [Admin Users UI](/admin-ui-identity-users#registration)
which enables management APIs and Admin UIs for managing Identity Auth Roles and Claims for both Users and Roles.
Once registered it will be available from the **Roles** menu item in the Admin UI sidebar which can be used Add and Remove Application Roles:

### Custom Application Roles
If your App uses an extended `IdentityRole` data model, it can be configured with:
```csharp
services.AddPlugin(
new AuthFeature(IdentityAuth.For(...)));
```
If it's also configured to use a different `PrimaryKey` type, it can be configured with:
```csharp
services.AddPlugin(
new AuthFeature(IdentityAuth.For(...)));
```
### IdentityAuth Role Claims
The Edit Role Admin UI also supports Adding and Remove Claims for a Role, e.g:

Any Added or Removed Claims are only applied after clicking **Update Role**, likewise you can exit the UI without applying any changes by clicking **Cancel**.
### Behavior of Role Claims
Claims added to Roles have similar behavior to having Claims individually applied to all Users with that Role such that
when a User is Authenticated they're populated with all claims assigned to their Roles and their individual User Claims.
## Validating Claims
::include admin-ui-claims-validation.md::
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/admin-ui-identity-users.md
---
title: Identity User Admin Feature
---
::: info
When using **ServiceStack Auth** refer to [Admin Users UI](/admin-ui-users) instead
:::
## Registration
The Identity Auth Admin UI can be enabled when registering the `AuthFeature` Plugin by calling `AdminUsersFeature()`:
```csharp
public class ConfigureAuth : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices(services => {
services.AddPlugin(new AuthFeature(IdentityAuth.For(
options => {
// options.SessionFactory = () => new CustomUserSession(); //optional
options.CredentialsAuth();
options.AdminUsersFeature();
})));
});
}
```
Which just like the ServiceStack Auth [Admin Users UI](/admin-ui-users) enables a
Admin UI that's only accessible to **Admin** Users for managing **Identity Auth** users at `/admin-ui/users`.
## User Search Results
Which displays a limited view of a User's info due to the minimal properties on the default `IdentityAuth` model:
### Custom Search Result Properties
These User Search results are customizable by specifying the `ApplicationUser` properties you want displayed instead:
```csharp
options.AdminUsersFeature(feature =>
{
feature.QueryIdentityUserProperties =
[
nameof(ApplicationUser.Id),
nameof(ApplicationUser.DisplayName),
nameof(ApplicationUser.Email),
nameof(ApplicationUser.UserName),
nameof(ApplicationUser.LockoutEnd),
];
});
```
### Custom Search Result Behavior
The default display Order of Users is also customizable:
```csharp
feature.DefaultOrderBy = nameof(ApplicationUser.DisplayName);
```
As well as the Search behavior which can be replaced to search any custom fields, e.g:
```csharp
feature.SearchUsersFilter = (q, query) =>
{
var queryUpper = query.ToUpper();
return q.Where(x =>
x.DisplayName!.Contains(query) ||
x.Id.Contains(queryUpper) ||
x.NormalizedUserName!.Contains(queryUpper) ||
x.NormalizedEmail!.Contains(queryUpper));
};
```
## Default Create and Edit Users Forms
The default Create and Edit Admin Users UI are also limited to editing the minimal `IdentityAuth` properties:
Whilst the Edit page includes standard features to lockout users, change user passwords and manage their roles:
### Custom Create and Edit Forms
By default Users are locked out indefinitely, but this can also be changed to lock users out to a specific date, e.g:
```csharp
feature.ResolveLockoutDate = user => DateTimeOffset.Now.AddDays(7);
```
The forms editable fields can also be customized to include additional properties, e.g:
```csharp
feature.FormLayout =
[
Input.For(x => x.UserName, c => c.FieldsPerRow(2)),
Input.For(x => x.Email, c => {
c.Type = Input.Types.Email;
c.FieldsPerRow(2);
}),
Input.For(x => x.FirstName, c => c.FieldsPerRow(2)),
Input.For(x => x.LastName, c => c.FieldsPerRow(2)),
Input.For(x => x.DisplayName, c => c.FieldsPerRow(2)),
Input.For(x => x.PhoneNumber, c =>
{
c.Type = Input.Types.Tel;
c.FieldsPerRow(2);
}),
];
```
That can override the new `ApplicationUser` Model that's created and any Validation:
### Custom User Creation
```csharp
feature.CreateUser = () => new ApplicationUser { EmailConfirmed = true };
feature.CreateUserValidation = async (req, createUser) =>
{
await IdentityAdminUsers.ValidateCreateUserAsync(req, createUser);
var displayName = createUser.GetUserProperty(nameof(ApplicationUser.DisplayName));
if (string.IsNullOrEmpty(displayName))
throw new ArgumentNullException(nameof(AdminUserBase.DisplayName));
return null;
};
```
### Admin User Events
Should you need to, Admin User Events can use used to execute custom logic before and after creating, updating and
deleting users, e.g:
```csharp
feature.OnBeforeCreateUser = (request, user) => { ... };
feature.OnAfterCreateUser = (request, user) => { ... };
feature.OnBeforeUpdateUser = (request, user) => { ... };
feature.OnAfterUpdateUser = (request, user) => { ... };
feature.OnBeforeDeleteUser = (request, userId) => { ... };
feature.OnAfterDeleteUser = (request, userId) => { ... };
```
### IdentityAuth User Claims
The User Claim Management UI can be used to assign Claims to individual Users:

## Validating Claims
::include admin-ui-claims-validation.md::
---
# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/admin-ui-profiling.md
---
title: Logging & Profiling UI
---
The Request Logging & Profiling UIs bring an invaluable new level of observability into your App, from being able to quickly inspect and browse incoming requests, to tracing their behavior from their generated events in the [Diagnostic Source](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.diagnosticsource?view=net-6.0) capabilities added all throughout ServiceStack, which both power the new UIs and enables new introspectability from code where you can now to tap in to inspect & debug when each diagnostic event occurs.
The quickest way to enable access to these new features to your App is with:
::: sh
npx add-in profiling
:::
Which will add the [Modular Startup](/modular-startup) configuration to your Host project that registers both Request Logging & Profiling features when running your App in [DebugMode](/debugging#debugmode) (i.e. Development):
```csharp
public class ConfigureProfiling : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices((context, services) => {
if (context.HostingEnvironment.IsDevelopment())
{
services.AddPlugin(new ProfilingFeature
{
IncludeStackTrace = true,
});
}
});
}
```
Whilst Request Logs can be added with:
::: sh
npx add-in requestlogs
:::
Or if you prefer to store Request Logs in an SQLite database:
::: sh
npx add-in sqlitelogs
:::
Or to store Request Logs in PostgreSQL, SQL Server or MySql:
::: sh
npx add-in db-requestlogs
:::
The default configuration looks at providing useful information during development, where the response request bodies are captured in the Request Logger and the StackTrace is captured on the important events where they can be useful.
### Configuration
Depending on your App you'll want to change these defaults, e.g. if you're persisting the request logs using the [CSV Request Logger](/request-logger#csv-request-logger) or [Redis Request Logger](/request-logger#redis-request-logger) it may not be feasible to **capture all API responses** if they're very large.
If enabled, **StackTraces** are captured in these important events:
- **ServiceStack:** Before a Service Gateway Request is sent
- **OrmLite:** Opening a connection or rolling back a transaction
- **Redis:** Opening a connection, auto retrying a failed command, renting & returning clients from a redis manager pool
The latter of which is useful when resolving [concurrent usage issues](/redis/troubleshooting).
As it adds overhead, profiling should only be added when used, e.g. during development or when needing to debug production issues. Although you may always want to capture request logs depending on how important it is to maintain an audit of completed API requests. Should it be needed, both Logging & Profiling plugins offer several configuration options to control the type, info & events captured.
Whichever features you have registered will dynamically appear in the Admin UI's sidebar for quick navigation:

### Request Logging UI
Clicking on **Logging** navigates to the Request Logging UI which displays each API request processed in a grid of useful summary information showing high-level information for each HTTP API request:

This screenshot shows an example of a non-authenticated user navigating to a protected page before signing in then querying and submitting a new Booking in the [AutoQuery CRUD Bookings Demo](/autoquery/crud-bookings) using [Locode's](/locode/) Auto UI, in which we can see error API Responses are highlighted in **red** and redirects highlighted in **yellow**.
The top navigation controls which results are displayed with:
- **Has Errors** - Show only requests with errors
- **Has Response** - Show only requests with response bodies
- **Reset Filters Icon** - Clear all filters (ESC)
- **Left/Right Icons** - Navigate to previous/next pages (LEFT/RIGHT)
- **Refresh Icon** - Reload the latest results
This same user workflow is also captured in the Profiling UI in much finer granularity, capturing all the events performed by APIs:

Clicking on an entry previews it in more detail, e.g. clicking on the first **/api/QueryBookings** will show the API Request and Response made:
By default it shows the Request and Response DTOs in JSON, but clicking on preview often shows a more human-friendly view:
A useful feature from having a dedicated UX-friendly UI is enabling quick navigation where each **blue** link will display results filtered to all matching requests, whilst the **trace request** link will navigate to the Profiling UI showing all diagnostic events performed within that request.
### Inspect Cookies and JWT Tokens
In addition to Request & Response DTOs, the Logging UI also shows all captured HTTP information including HTTP Request Headers with any Cookies being extracted into its own view for better readability as well as decoded JWT payload from the **ss-tok** cookie when using [JWT Auth](/auth/jwt-authprovider) with non-encrypted JWT defaults.
Lets now take a look at the failed **CreateBooking** request to see what went wrong:
Ok, so the Admin User (identified from JWT info) tried to create an empty booking which was rejected by its server declarative validation rules which sees these context validation errors surfaced into Locode's UI:
We can then see this was quickly rectified in the next request with a successful Booking submitted:
Clicking on **trace request** we can see all the diagnostic events performed in this API request within the **RequestBefore** and **RequestAfter** events which took **0.07s** to complete.
## Profiling UI
Following diagnostic conventions you'll typically see 2 entries for each event, created before and after each action, measuring the duration and capturing the last event before any error occurred.

### SQL Profiling
Clicking on an entry will show more useful contextual information captured for each event, e.g. if you click on OrmLite's **CommandAfter** event you'll be able to see the generated SQL + Params executed by OrmLite:
The profiling detail view also contains **blue** links to filter matching diagnostic events and showing useful information like the **Thread**, **User** this command was executed by as well as the **duration** and **timestamp** when it occurred.
### Redis Profiling
Redis simpler commands are captured in a list of arguments:
### Purchase API Events Example
Surfacing the high-level events of your service implementations provides a new observability perspective that's harder to infer from trying to follow the details in the code.
For example our [Order Page](https://account.servicestack.net/buy/BUS) generated over **150+ events** capturing all the SQL commands to store order, subscription, customer, payment information and generated License and Order confirmation emails, HttpClient integration requests with Stripe and MQ requests for sending emails in a [Background MQ Worker thread](/background-mq).

### HttpClient Profiling
HttpClient profiling is implemented a little differently then other events in that it builds on the existing HttpClient diagnostic events so it's able to capture general usage of .NET's HttpClient, which is how it's able to capture our [integration with Stripe](/stripe):
### JsonApiClient Profiling
Although we're able to provide richer profiling for our .NET 10+ [JsonApiClient](/csharp-client#jsonapiclient) which has access to typed Request DTOs for submitting API Requests:
As well as Response DTOs returned in API Responses:
We also can examine API Error responses in richer detail, e.g:
### MQ Profiling
Since they execute APIs on an entirely different endpoint and worker threads, MQ Requests are tracked independently from HTTP APIs starting their own diagnostic Activity which enables being able to trace all events generated from an MQ Request. Here's an example used to handle sending customer emails:
### Service Gateway Profiling
The [Service Gateway](/service-gateway) leverages ServiceStack's message-based design to enable loosely-coupled service integrations enabling systems to split into Microservices without needing to change any of the internal services consuming them. As they're not RPC invocations their messages are introspectable and can be observed in the Profiling UI:
### Profile Custom Info
We've made it easy to add a custom tracking field with the same functionality as the primary fields where they can be sorted and filtered. This could be used to attach a **Tenant Id** to the profiling information by providing a Label and Resolver function to resolve it, e.g:
```csharp
new ProfilingFeature {
TagLabel = "Tenant",
TagResolver = req => MyResolveTenant(req),
}
```
Where it will be displayed in all profiling results, e.g:

::: tip
The number and order of fields can be customized in `SummaryFields` collection in `ProfilingFeature`
:::
This custom info also appears in the detail page as a link which can be used to filter events with the same tenant id:
### Profile Custom Metadata
You're also able to capture custom information for different events and have them appear in the detail page, e.g:
```csharp
new ProfilingFeature {
DiagnosticEntryFilter = (entry, evt) => {
if (evt is RequestDiagnosticEvent requestEvent)
{
var req = requestEvent.Request;
entry.Meta = new() {
["RemoteIp"] = req.RemoteIp,
["Referrer"] = req.UrlReferrer?.ToString(),
["Language"] = req.GetHeader(HttpHeaders.AcceptLanguage),
};
}
},
}
```
Where it will be populated in the **Meta** section arguments:
### Access Diagnostic Events in Code
In addition to powering the profiling UI, the diagnostic events added throughout ServiceStack can be observed in code to tap in and inspect when these diagnostic events occur. It follows the standard Diagnostic Source model where you specify which listeners you want observed in `OnNext(DiagnosticListener)` that you can then access in `OnNext(KeyValuePair)`.
Microsoft's Diagnostic Events like HttpClient uses anonymous classes making them unnecessarily difficult to access, which can be made easier by using our [Reflection Utils ToObjectDictionary()](/reflection-utils#converting-instances-from-an-object-dictionary).
As they offer better utility, we've opted to use idiomatic strong types and string constants instead where they're better accessible from C#.
You can use this skeleton class for a quick way to get started showing how to subscribe to all ServiceStack Diagnostic Sources and the event names and types to handle all profiling events:
```csharp
// Register your Diagnostic Observer
var observer = new MyDiagnosticObserver();
var subscription = DiagnosticListener.AllListeners.Subscribe(observer);
public sealed class MyDiagnosticObserver :
IObserver,
IObserver>
{
private readonly List subscriptions = new();
/* Specify which Profiling Events you want to observe */
void IObserver.OnNext(DiagnosticListener diagnosticListener)
{
if (diagnosticListener.Name is Diagnostics.Listeners.ServiceStack
|| diagnosticListener.Name is Diagnostics.Listeners.OrmLite
|| diagnosticListener.Name is Diagnostics.Listeners.Redis
|| diagnosticListener.Name is Diagnostics.Listeners.Client
|| diagnosticListener.Name is Diagnostics.Listeners.HttpClient)
{
var subscription = diagnosticListener.Subscribe(this);
subscriptions.Add(subscription);
}
}
/* Handle Profiling Events */
public void OnNext(KeyValuePair kvp)
{
/** ServiceStack */
/*** Request */
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteRequestBefore && kvp.Value is RequestDiagnosticEvent reqBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteRequestAfter && kvp.Value is RequestDiagnosticEvent reqAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteRequestError && kvp.Value is RequestDiagnosticEvent reqError) { /*...*/ }
/*** Gateway */
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteGatewayBefore && kvp.Value is RequestDiagnosticEvent gatewayBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteGatewayAfter && kvp.Value is RequestDiagnosticEvent gatewayAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteGatewayError && kvp.Value is RequestDiagnosticEvent gatewayError) { /*...*/ }
/*** MQ */
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteMqRequestBefore && kvp.Value is MqRequestDiagnosticEvent mqReqBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteMqRequestAfter && kvp.Value is MqRequestDiagnosticEvent mqReqAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteMqRequestError && kvp.Value is MqRequestDiagnosticEvent mqReqError) { /*...*/ }
if (kvp.Key == Diagnostics.Events.ServiceStack.WriteMqRequestPublish && kvp.Value is MqRequestDiagnosticEvent mqReqPublish) { /*...*/ }
/** Client */
if (kvp.Key == Diagnostics.Events.Client.WriteRequestBefore && kvp.Value is HttpClientDiagnosticEvent clientBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Client.WriteRequestAfter && kvp.Value is HttpClientDiagnosticEvent clientAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Client.WriteRequestError && kvp.Value is HttpClientDiagnosticEvent clientError) { /*...*/ }
/** HttpClient */
if (kvp.Key == Diagnostics.Events.HttpClient.OutStart)
{
var obj = kvp.Value.ToObjectDictionary();
}
if (kvp.Key == Diagnostics.Events.HttpClient.Request)
{
var obj = kvp.Value.ToObjectDictionary();
}
if (kvp.Key == Diagnostics.Events.HttpClient.OutStop)
{
var obj = kvp.Value.ToObjectDictionary();
}
if (kvp.Key == Diagnostics.Events.HttpClient.Response)
{
var obj = kvp.Value.ToObjectDictionary();
}
/** OrmLite */
if (kvp.Key == Diagnostics.Events.OrmLite.WriteCommandBefore && kvp.Value is OrmLiteDiagnosticEvent dbBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteCommandAfter && kvp.Value is OrmLiteDiagnosticEvent dbAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteCommandError && kvp.Value is OrmLiteDiagnosticEvent dbError) { /*...*/ }
/*** OrmLite Connections */
if (kvp.Key == Diagnostics.Events.OrmLite.WriteConnectionOpenBefore && kvp.Value is OrmLiteDiagnosticEvent dbOpenBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteConnectionOpenAfter && kvp.Value is OrmLiteDiagnosticEvent dbOpenAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteConnectionOpenError && kvp.Value is OrmLiteDiagnosticEvent dbOpenError) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteConnectionCloseBefore && kvp.Value is OrmLiteDiagnosticEvent dbCloseBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteConnectionCloseAfter && kvp.Value is OrmLiteDiagnosticEvent dbCloseAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteConnectionCloseError && kvp.Value is OrmLiteDiagnosticEvent dbCloseError) { /*...*/ }
/*** OrmLite Transactions */
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionOpen && kvp.Value is OrmLiteDiagnosticEvent commitOpen) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionCommitBefore && kvp.Value is OrmLiteDiagnosticEvent commitBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionCommitAfter && kvp.Value is OrmLiteDiagnosticEvent commitAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionCommitError && kvp.Value is OrmLiteDiagnosticEvent commitError) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionRollbackBefore && kvp.Value is OrmLiteDiagnosticEvent rollbackBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionRollbackAfter && kvp.Value is OrmLiteDiagnosticEvent rollbackAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.OrmLite.WriteTransactionRollbackError && kvp.Value is OrmLiteDiagnosticEvent rollbackError) { /*...*/ }
/** Redis */
if (kvp.Key == Diagnostics.Events.Redis.WriteCommandBefore && kvp.Value is RedisDiagnosticEvent redisBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteCommandRetry && kvp.Value is RedisDiagnosticEvent redisRetry) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteCommandAfter && kvp.Value is RedisDiagnosticEvent redisAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteCommandError && kvp.Value is RedisDiagnosticEvent redisError) { /*...*/ }
/*** Redis Connections */
if (kvp.Key == Diagnostics.Events.Redis.WriteConnectionOpenBefore && kvp.Value is RedisDiagnosticEvent redisOpenBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteConnectionOpenAfter && kvp.Value is RedisDiagnosticEvent redisOpenAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteConnectionOpenError && kvp.Value is RedisDiagnosticEvent redisOpenError) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteConnectionCloseBefore && kvp.Value is RedisDiagnosticEvent redisCloseBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteConnectionCloseAfter && kvp.Value is RedisDiagnosticEvent redisCloseAfter) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WriteConnectionCloseError && kvp.Value is RedisDiagnosticEvent redisCloseError) { /*...*/ }
/*** Redis Pools */
if (kvp.Key == Diagnostics.Events.Redis.WritePoolRent && kvp.Value is RedisDiagnosticEvent redisPoolBefore) { /*...*/ }
if (kvp.Key == Diagnostics.Events.Redis.WritePoolReturn && kvp.Value is RedisDiagnosticEvent redisPoolAfter) { /*...*/ }
}
void IObserver.OnCompleted()
{
subscriptions.ForEach(x => x.Dispose());
subscriptions.Clear();
}
public void OnCompleted() {}
void IObserver.OnError(Exception error) {}
public void OnError(Exception error) {}
}
```
### Request Logs Configuration
The [Request Logs](/request-logger) feature has a number of configuration options controlling which requests are logged and the level of logging captured about them.
```csharp
class RequestLogsFeature
{
// Limit API access to users in role
string AccessRole = RoleNames.Admin;
// RequestLogs service Route, default is /requestlogs
string AtRestPath = "/requestlogs";
// Size of memory logger circular buffer
int? Capacity;
// Turn On/Off Session Tracking
bool EnableSessionTracking;
// Turn On/Off Logging of Raw Request Body, default is Off
bool EnableRequestBodyTracking;
// Turn On/Off Raw Request Body Tracking per-request
Func RequestBodyTrackingFilter;
// Turn On/Off Tracking of Responses
bool EnableResponseTracking = false;
// Turn On/Off Tracking of Responses per-request
Func ResponseTrackingFilter;
// Turn On/Off Tracking of Exceptions
bool EnableErrorTracking = true;
// Don't log matching requests
Func SkipLogging;
// Change the RequestLogger provider. Default is InMemoryRollingRequestLogger
IRequestLogger RequestLogger;
// Don't log requests of these types. By default RequestLog's are excluded
Type[] ExcludeRequestDtoTypes;
// Don't log request body's for services with sensitive information.
// By default Auth and Registration requests are hidden.
Type[] HideRequestBodyForRequestDtoTypes;
// Don't log Response DTO Types
Type[] ExcludeResponseTypes;
// Limit logging to only Service Requests
bool LimitToServiceRequests = true;
// Customize Request Log Entry
Action RequestLogFilter;
// Ignore logging and serializing these Request DTOs
List IgnoreTypes; = new();
// Use custom Ignore Request DTO predicate
Func