Angel3 Developer Guide
  • README
  • Foreword
  • Tutorial
    • Getting Started
    • Minimal Setup
  • Command Line Interface
    • Setup
  • Templates and Views
    • Server Side Rendered Views
    • JAEL3
      • About
      • Basics
      • Custom Elements
      • Strict Resolution
      • Directive: declare
      • Directive: for-each
      • Directive: extend
      • Directive: if
      • Directive: include
      • Directive: switch
  • Authentication
    • About
    • Strategies
    • Local
  • Databases
    • Object Relational Mapping (ORM)
      • About
      • Basic Functionality
      • Relations
      • Migrations
      • PostgreSQL
    • NoSQL
  • Extensions and Plugins
    • Using Plug-ins
    • Writing a Plugin
  • Under the hood
    • Basic Routing
    • Requests & Responses
    • Request Lifecycle
    • Dependency Injection
    • Middleware
    • Controllers
    • Parsing Request Bodies
    • Serialization
    • Service Basics
    • Testing
    • Error Handling
    • Pattern Matching and Parameter
  • Angel Framework Migration
    • Angel 2.x.x to Angel3
      • Rationale - Why a new Version?
      • Framework Changelog
      • 3.0.0 Migration Guide
    • Angel 1.x.x to 2.x.x
      • Framework Changelog
      • 2.0.0 Migration Guide
  • Packages
    • Authentication
    • CORS
    • Database-Agnostic Relations
    • Configuration
    • Databases
      • ORM
      • MongoDB
      • JSON File-based
      • RethinkDB
    • Templates and Views
      • Jael template engine
      • Mustache Templates
      • compiled_mustache-based engine
      • html_builder-based engine
      • Markdown template engine
      • Using Angel with Angular
    • Hot Reloading
    • Pagination
    • Polling
    • Production Utilities
    • REST Client
    • Reverse Proxy
    • Router
    • Serialization
    • Service Seeder
    • Static Files
    • Security
    • Server-sent Events
    • shelf Integration
    • Task Engine
    • User Agents
    • Validation
    • Websockets
  • Resources
    • Dependency Injection Patterns
    • Example Projects
    • YouTube Tutorials
    • Ecosystem
Powered by GitBook
On this page
  • Controllers
  • @Expose()
  • Allowing Null Values
  • Named Controllers and Actions
  • Interacting with Requests and Responses
  • Transforming Data
  • Next Up

Was this helpful?

  1. Under the hood

Controllers

PreviousMiddlewareNextParsing Request Bodies

Last updated 3 years ago

Was this helpful?

Controllers

Angel3 has built-in support for controllers. This is yet another way to define routes in a manageable group, and can be leveraged to structure your application in the format. You can also use the method of any .

The metadata on controller classes is processed via reflection only once, at startup. Do not believe that your controllers will be crippled by reflection during request handling, because that possibility is eliminated by .

import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_container/mirrors.dart';

@Expose("/todos")
class TodoController extends Controller {

  @Expose("/:id")
  getTodo(id) async {
    return await someAsyncAction();
  }

  // You can return a response handler, and have it run as well. :)
  @Expose("/login")
  login() => auth.authenticate('google');
}

main() async {
  Angel app = Angel(reflector: MirrorsReflector());
  await app.configure(TodoController().configureServer);
}

@Expose()

The glue that holds it all together is the Expose annotation:

class Expose {
  final String method;
  final Pattern path;
  final List middleware;
  final String as;
  final List<String> allowNull;

  const Expose(Pattern this.path,
      {String this.method: "GET",
      List this.middleware: const [],
      String this.as: null,
      List<String> this.allowNull: const[]});
}

Allowing Null Values

Most fields are self-explanatory, save for as and allowNull. See, request parameters are mapped to function parameters on each handler. If a parameter is null, an error will be thrown. To prevent this, you can pass its name to allowNull.

@Expose("/foo/:id?", allowNull: const["id"])

Named Controllers and Actions

The other is as. This allows you to specify a custom name for a controller class or action. ResponseContext contains a method, redirectToAction that can redirect to a controller action.

@Expose("/foo")
class FooController extends Controller {
  @Expose("/some/strange/url/:id", as: "bar")
  someActionWithALongNameThatWeWouldLikeToShorten(int id) async {
  }
}

main() async {
  Angel app = Angel();

  app.get("/some/path", (req, res) async => res.redirectToAction("FooController@bar", {"id": 1337}));
}

If you do not specify an as, then controllers and actions will be available by their names in code. Reflection is cool, huh?

Interacting with Requests and Responses

@Expose("/hello")
class HelloController extends Controller {
  @Expose("/")
  Future getIndex(ResponseContext res) async {
    await res.render("hello");
  }
}

Transforming Data

Future<bool> deserializeUser(RequestContext req, res) async {
  var id = req.params['id'] as String;
  req.params['user'] = await asyncFetchUser(id);

  return true;
}

@Expose("/user", middleware: const [deserializeUser])
class UserController extends Controller {

  @Expose("/:id/name")
  Future<String> getUserName(User user) async {
    return user.username;
  }

}

main() async {
  Angel app = Angel();
  await app.configure(UserController().configureServer);
}

Next Up

Rather than extending from Routable, controllers act as when called. This pseudo-plugin will wire all your routes for you.

Controllers can also interact with . All you have to do is declare a RequestContext or ResponseContext as a parameter, and it will be passed to the function.

You can use to de/serialize data to be processed in a controller method.

How to with Angel3

plugins
requests and responses
middleware
handle parse request bodies
Using Angel3 Plug-ins
MVC
Router
pre-injecting dependencies
Controllers
@Expose()
Allowing Null Values
Named Controllers and Actions
Interacting with Requests and Responses
Transforming Data
Next Up...
group()