Skip to content

File-based routing #66

Description

@Atulin

Having to prefix all endpoints of a given type with a part of a path can be tedious and error-prone. What is not tedious or error-prone, is using the filesystem to drive routing.

Current state:

To have an endpoint at POST: /api/public/products we need:

// location: Api/Public/Products/CreateProduct.cs

[Handler]
[HttpPost("api/public/porducts")]
public static partial CreateProduct
{
    // ...
}

Can you spot the typo?

Proposed

To have an endpoint at POST: /api/public/products is as simple as:

// location: Api/Public/Products/CreateProduct.cs

[Handler]
[HttpPost]
public static partial CreateProduct
{
    // ...
}

Considerations

Opt-in methods

It does not have to be the default behavior. It could be controlled globally with some [assembly: FilesystemRouting] attribute, or perhaps on the individual endpoint basis with a similar attribute, or some magic like [HttpPost("[file]")] or [HttpPost(FilesystemRouting = true)]

Naming policies

What happens when a path contains a space? Should PascalCase directories be translated to lowercase, kebab-case, or something else?

The easiest way would be to go with what is the default for Microsoft, or at least seems to be: whitespace and special characters get removed, everything gets translated into PascalCase.

The best way would be to provide a choice, for example via an enum:

public enum NamingPolicy
{
    PascalCase,
    CamelCase,
    LowerCase,
    KebabCase,
    SnakeCase
}

to be used with attributes discussed prior, for example

[assembly: FileSystemRouting(
    NamingPolicy = NamingPolicy.LowerCase
)]

Base path

Endpoints don't always have to be placed in a directory at the root of the project. For various reasons, they can be placed elsewhere. A way should be provided to define the base directory. For example:

// location: Api/Handlers/Product/Create.cs

[assembly: FileSystemRouting(
    RootDirectory = "Api/Handlers"
)]

[Handler]
[MapPost] // maps it to POST: /product
public static partial class CreateProduct
{
    // ...
}

Source generator limitations

File location might not be available to a source generator. In such a case, should the namespace be used as a close approximation?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions