Skip to content

Route Management

First route

In AventusSharp, each public method within a Router class is automatically treated as a route. By default, the route names correspond to the method names and use the GET HTTP method. For example, the code below defines two routes: / (GET) since Index is an alias for /, and /test (GET).

AventusSharp final URLs are always lowercase.

Be sure not to define any constructors in your routers.

MainRouter.cs
using AventusSharp.Routes;
namespace Demo.Routes
{
public class MainRouter : Router
{
// Route: url / (GET)
public string Index() {
return "It's working";
}
// Route: url /test (GET)
public string Test() {
return "It's a test";
}
}
}

Return Types

In AventusSharp, each route returns a response handled via an IResponse interface. There are several default response types based on the return type of your route:

  • If the route returns an IResponse directly, it is processed as-is.
  • If the route returns void, the response will be empty, with a status code of 204 (No Content).
  • If the route returns a byte[] array, a ByteResponse will be used.
  • If the route returns a text value, a TextResponse is applied.
  • For all other types, a JsonResponse is used by default.
MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Attributes;
using AventusSharp.Routes.Response;
using Demo.Data;
namespace Demo.Routes
{
public class MainRouter : Router
{
// Route: url / (GET), returns a TextResponse
public string Index() {
return "It's working";
}
// Route: url /test (GET), explicitly returns a TextResponse
public TextResponse Test() {
return new TextResponse("It's a test");
}
// Route: url /test2 (GET), returns a JsonResponse by default
public User Test2() {
return new User();
}
}
}

List of predefined IResponse:

  • DummyResponse: Returns a fixed response with the text “I’m dummy.”
  • ByteResponse: Sends a byte array as the response body, with the byte array passed into the constructor.
  • JsonResponse: Serializes an object to JSON using the configuration’s JSON settings.
  • TextResponse: Sends a plain text response with the specified text.
  • View: Renders an HTML view from the ViewDir directory specified in the configuration.
  • ViewDynamic: Renders a dynamic view using the Scriban templating engine. Requires the Scriban NuGet package.

Static Views

To return a static HTML view, use the View response type. The HTML file should be placed in the configured ViewDir directory (by default Views).

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Response;
namespace Demo.Routes
{
public class MainRouter : Router
{
public View Index() {
return new View("index");
}
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>

Dynamic Views

To return a dynamic HTML view, use the ViewDynamic response type, which leverages Scriban templating for dynamic content rendering. Install Scriban with:

Terminal window
dotnet add package Scriban

Then you can create your route :

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Response;
namespace Demo.Routes
{
public class MainRouter : Router
{
public ViewDynamic Index() {
return new ViewDynamic("index", new
{
name = "John",
});
}
}
}

This file should also be placed in the configured ViewDir directory. It uses Scriban syntax for dynamic content, like {{name}}, which will be replaced at runtime.

index.sbnhtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>Hello {{name}}</p>
</body>
</html>

You can also implement custom response types if needed.

With this setup, you have full flexibility in defining and managing your routes in AventusSharp.

Changing HTTP Methods

To define routes with HTTP methods other than GET, use attributes like [Get], [Post], [Put], [Delete], and [Options]. This allows you to customize each route’s HTTP method as needed.

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Attributes;
namespace Demo.Routes
{
public class MainRouter : Router
{
[Get]
public string Index() {
return "It's working";
}
// Route: url /test (POST)
[Post]
public string Test() {
return "It's a test";
}
}
}

Custom URL Definitions

Prefixing Routes

You can add a prefix to all routes within a router using the [Prefix(string)] attribute. This helps in grouping related routes under a common path.

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Attributes;
namespace Demo.Routes
{
[Prefix("Main")]
public class MainRouter : Router
{
// Route: url => /main/ (GET)
public string Index() {
return "It's working";
}
// Route: url => /main/test (GET)
public string Test() {
return "It's a test";
}
}
}

Customizing Individual Route Paths

To rename individual routes, use the [Path(string)] attribute. This allows you to define a unique path for each route.

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Attributes;
using Path = AventusSharp.Routes.Attributes.Path;
namespace Demo.Routes
{
[Prefix("Main")]
public class MainRouter : Router
{
// Route: url => /main/ (GET)
public string Index() {
return "It's working";
}
// Route: url => /main/demo (GET)
[Path("/Demo")]
public string Test() {
return "It's a test";
}
}
}

URL Parameters

You can add parameters to routes by enclosing them in {} within the path. The parameters should be defined as function arguments, and AventusSharp will automatically infer their types.

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Attributes;
using Path = AventusSharp.Routes.Attributes.Path;
namespace Demo.Routes
{
[Prefix("Main")]
public class MainRouter : Router
{
// Route: url => /main/ (GET)
public string Index() {
return "It's working";
}
// Route: url => /main/demo/{id} (GET), where {id} is inferred as an integer
[Path("/Demo/{id}")]
public string Test(int id) {
return "It's a test for " + id;
}
}
}

Calling Functions

You can also call functions within routes. This approach is useful when creating abstract classes for generic routers. Function calls in routes are executed at route initialization, so only predefined elements should be included. This functionality is demonstrated in the StorableRouter class, which will be discussed later.

MainRouter.cs
using AventusSharp.Routes;
using Path = AventusSharp.Routes.Attributes.Path;
namespace Demo.Routes
{
public class MainRouter : Router
{
// Route: url => / (GET)
public string Index() {
return "It's working";
}
// Route: url => /mainrouter/{id} (GET), where router name is generated by GetRouterName()
[Path("/[GetRouterName]/{id}")]
public string Test(int id) {
return "It's a test for " + id;
}
protected string GetRouterName() {
return GetType().Name;
}
}
}

With these tools, you can efficiently manage HTTP methods, customize URLs, handle parameters, and add dynamic functionality within your routes.

Service Injection

AventusSharp supports injecting services that can be directly used within routes. In the example below, we’ll create a simple service to provide the current date and time.

public interface IDateTime
{
DateTime Now { get; }
}
public class SystemDateTime : IDateTime
{
public DateTime Now => DateTime.Now;
}

To register a service for injection, use the static Inject function during application initialization.

private static void InitHttp(VoidWithError initResult, WebApplication app)
{
RouterMiddleware.Configure((config) => {});
initResult.Run(RouterMiddleware.Register);
app.Use(RouterMiddleware.OnRequest);
// Inject IDateTime service implementation
RouterMiddleware.Inject<IDateTime, SystemDateTime>();
}

Once injected, you can use IDateTime in any route by including it as a parameter.

MainRouter.cs
using AventusSharp.Routes;
using Demo.Logic;
using Path = AventusSharp.Routes.Attributes.Path;
namespace Demo.Routes
{
public class MainRouter : Router
{
public string Time(IDateTime dateTime)
{
return "It's " + dateTime.Now;
}
}
}

Request Body

Any additional parameters in a route method signature will be treated as part of the request body. To enable this functionality, install the HttpMultipartParser NuGet package:

Terminal window
dotnet add package HttpMultipartParser

Then you can create route with a body

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Routes.Attributes;
namespace Demo.Routes
{
public class MainRouter : Router
{
[Post]
public string Hello(string name)
{
return "Hello " + name;
}
}
}

Now, you can send a request with a JSON or form body containing a name field, and it will be automatically injected into the Hello method.

Voici une version reformulée en anglais et formatée en Markdown pour votre documentation :

Excluding a Method from Routing

If you have a public method in your router that you do not want to expose as a route, you can use the [NoRoute] attribute. This prevents the method from being registered as an http route.

MainRouter.cs
using AventusSharp.Routes;
using AventusSharp.Tools.Attributes;
namespace Demo.Routes
{
public class MainRouter : WsRouter
{
public string Index()
{
return "It's working";
}
// The route /test won't exist
[NoRoute]
public string Test()
{
return "It's a test";
}
}
}

In this example, the /test route won’t be created, even though the Test method is public.


Preconfigured HTTP Routes

AventusSharp provides a preconfigured HTTP router called StorableRouter<T>. This generic router simplifies the creation of HTTP routes for managing storable objects. The type parameter T represents the object type you want to handle, and the name of T is used in place of [StorableName] in the route paths.

The following routes are automatically created:

FunctionPathHTTP Method
GetAll/[StorableName]GET
Create/[StorableName]POST
CreateMany/[StorableName]sPOST
GetById/[StorableName]/{id}GET
GetByIds/[StorableName]/GetByIdsGET
Update/[StorableName]/{id}PUT
UpdateMany/[StorableName]sPUT
Delete/[StorableName]/{id}DELETE
DeleteMany/[StorableName]sDELETE

Key Benefits

  • Ease of Use: No need to manually define standard CRUD routes.
  • Standardized API: Ensures consistent HTTP routing for all your storable objects.
  • Rapid Development: Focus on the logic and let the router handle the routing structure.

Example Usage

To create a router for a specific storable object, simply inherit from StorableRouter<T> and specify your object type as the generic parameter. All the routes described above will be automatically available.

UserRouter.cs
using AventusSharp.Routes;
using Demo.Data;
namespace Demo.Routes
{
public class UserRouter : StorableRouter<User>
{
}
}

This feature makes setting up HTTP routes for your objects fast and straightforward, saving time and ensuring consistency across your application.