-
-
Notifications
You must be signed in to change notification settings - Fork 12
Controllers
- Summary
- Object Model
- Inherited Actions
- Injected Dependencies
- Authentication
- Authorization
- Model Validation
- Error Handling
- Security
- TimeZone
- Virus Scan
- Localization
- Documentation
- Versioning
- Custom Headers
- Content Type Negotiation
- Serialization / Deserialization
- Health Checks
Nano includes a few base controller classes, providing derived functionality for model model validation, content-type negotiation, exception handling and more. Furthermore, deriving controllers inherit a rich set of action methods for adding, updating, deleting and querying the model implemented by the controller.
Additionally, Nano includes the following concrete controllers.
-
AuditController
Read-only actions for exposing audit logging entries, if audit is enabled. -
AuthController
Login and logoff actions. -
HomeController
General purpose actions, Nano implemented. -
IdentityController
Identity management actions.
The BaseController<TRepository, TEntity, TIdentity, TCriteria>
abstract class implementation, is as shown defined by four generic type parameters.
-
TRepository
, defines the underlying implementation of theIRepository
interface. -
TEntity
, defines the entity of the controller. -
TIdentity
, defines the identity type used by the entity related to finding entity by a unique identifier. -
TCriteria
, defines the query criteria implementation related to querying the entity.
Normally, there is no reason to derive implementations directly from the BaseController<TRepository, TEntity, TIdentity, TCriteria>
. Deriving from the DefaultController<MyEntity, MyQueryCriteria>
is equivalent to BaseController<DefaultRepository, TEntity, Guid, TCriteria>
, where as shown, the TRepository
parameter is defined as DefaultRepository
, and TIdentity
is of type System.Guid
.
In situations where only read-only actions is permitted on the model associated with a controller, Nano has the DefaultControllerReadOnly
to support that. When deriving from that, only query actions are inherited. Additionally, Nano also provides default controller implementations for Creatable-
, Updatable-
and DeletableController
, if needed.
Additionally, some other controllers exists in Nano as well. These controllers differ in the generic parameter types, to allow for a more flexible use. For example, if no data repository is required by the application, a controller exists where the generic parameter TRepository
is omitted.
public class MyController : DefaultController<MyEntity, MyQueryCriteria>
{
public MyController(ILogger logger, IRepository repository, IEventing eventing)
: base(logger, repository, eventing)
{ }
}
The IdentityController<TEntity, TCriteria>
contains methods for creating and managing identities used to authenticate with the application. Derive a controller implementation from IdentityController<TEntity, TCriteria>
, and inherit all the identity actions.
The IdentityController<TEntity, TCriteria>
derives from DefaultControllerUpdatable<TEntity, TCriteria>
, allowing identities to only be updated (and fetched, naturally), but may only be created through the inherited identity action signup
.
public class MyController : IdentityController<MyEntity, MyQueryCriteria>
{
public MyController(ILogger logger, IRepository repository, IEventing eventing, IdentityManager identityManager)
: base(logger, repository, eventing, identityManager)
{ }
}
When deriving a controller implementation from DefaultController<MyEntity, MyQueryCriteria>
, a rich set of action methods are inherited through the BaseControllerReadOnly<MyEntity, MyQueryCriteria>
and the BaseControllerWriteable<MyEntity, MyQueryCriteria>
abstract controller implementations.
Routing requests to controller actions, is done using the default convention, as shown below
http(s)://{host}:{port}/{root}/{controller}/{action}/{Id?}
-
Index (GET / POST)
, get a list of models (pagination, ordering). -
Details (GET)
, get details about a model. -
Details Many (POST)
, get details about many models. -
Query (GET / POST)
, query for many models (criteria, pagination, ordering). -
Query First (GET / POST)
, query for first model (criteria, pagination, ordering). -
Query Count (GET / POST)
, query for number of models (criteria).
-
Create (POST)
, create a model. -
Create And Get (POST)
, create a model and reloads the model. -
Create Many (POST)
, create many models. -
Create Many Bulk (POST)
, create bulk many models. -
Edit (POST / PUT)
, update a model. -
Edit And Get (POST / PUT)
, update a model and reloads the model. -
Edit Many (POST / PUT)
, update many models. -
Edit Many Query (POST / PUT)
, update many models based on a query. -
Edit Many Bulk (POST / PUT)
, update bulk many models. -
Delete (POST / DELETE)
, gets the html 'delete' view. -
Delete (POST / DELETE)
, delete a model. -
Delete Many (POST / DELETE)
, delete many models. -
Delete Many Query (POST / DELETE)
, delete many models based on a query. -
Delete Many Bulk (POST / DELETE)
, delete bulk many models.
-
ping
Ping. -
user
Get information about the current user. -
language
Sets the language in a cookie, for use with following requests. -
timezone
Sets the timezone in a cookie, for use with following requests.
-
login
authenticating a user and returns an access token (jwt). -
login/refresh
refreshes the login and creates a new access token (jwt). -
login/external/direct
sign-in a user, from data received from a separate external authentication. -
login/external/direct/transient
sign-in a user transient, from data received from a separate external authentication. -
login/external/google
sign-in a user, using Google external provider. -
login/external/google/transient
sign-in a user, using Google external provider. -
login/external/facebook
sign-in a user, using Facebook external provider. -
login/external/facebook/transient
sign-in a user, using Facebook external provider. -
login/external/microsoft
sign-in a user, using Microsoft external provider. -
login/external/microsoft/transient
sign-in a user, using Microsoft external provider. -
external/google/data
get external data and access token from Google. Use withlogin/external/direct
. -
external/facebook/data
get external data and access token from Facebook. Use withlogin/external/direct
. -
external/microsoft/data
get external data and access token from Microsoft. Use withlogin/external/direct
. -
external/schemes
returns all configured external login providers.
-
signup
Registers a new user. -
signup/external/direct
registers a new user using an external login provider data retrieved separately. Use withexternal/{provider}/data
-
signup/external/google
sign-up a user, using Google external provider. -
signup/external/facebook
sign-up a user, using Facebook external provider. -
signup/external/microsoft
sign-up a user, using Microsoft external provider. -
username/set
Sets a username for a user. -
password/set
Sets a password for a user. -
password/reset
Resets the password of a user. -
password/reset/token
Generates an reset password token for a user. -
password/change
Changes the password of a user. -
password/options
Get the password options. -
email/change
Changes the email address of a user -
email/change/token
Generates an change email token for a user. -
email/confirm
Confirms the email of a user. -
email/confirm/token
Generates an email confirmation token for a user. -
phone/change
Changes the phone number of a user -
phone/change/token
Generates an change phone token for a user. -
phone/confirm
Confirms the phone of a user. -
phone/confirm/token
Generates an phone confirmation token for a user. -
external/login/remove
Removes the external login of a user. -
roles/{id}
gets roles of a user. -
roles/assign
assign a role to a user. -
roles/remove
remove a role from a user. -
claims
get claims of a user. -
claims/assign
assign a claim to a user. -
claims/remove
assign a claim from a user. -
delete
delete a user. -
delete/many
delete many users.
Nano controllers has three dependencies injected into the constructor, all of which is registered when building the application. Derived controller implementations can add further injections as needed.
-
ILogger
, is the interface for logging in the controller. -
IRepository
, is the interface for get, add, update, delete and query data in the controller. -
IEventing
, is the interface for publishing events in the controller.
When authentication has been enabled and configured, and the application is running, users authenticate in order to gain access to the controllers and their actions. Nano has a AuthController
implementation, responsible for this.
Nano supports various methods of authentication as described in Security - Authentication section.
When a user successfully authenticates, a jwt-token is returned to the client. Subsequent requests must include the Authorization
header, containing the value Baerer {token}
. See JWT Explained for further details.
In Nano the HttpContext
is extended with methods, that decrypts the authorization token, and extracts specific claim values.
-
GetIsAnonymous()
Returns whether the user is anonymous. -
GetJwtAppId()
Returns app id. -
GetJwtToken()
Returns the complete token. -
GetJwtUserId()
Extracts the user-id of the logged in user. -
GetJwtUserName()
Extracts the user username of the logged in user. -
GetJwtUserEmail()
Extracts the user email address of the logged in user. -
GetJwtExternalToken()
Extracts the external provider access token, if logged in with external provider.
All methods returns null, when not authenticated and no authorization token is passed along with the request.
By default, authorization to controller actions is handling by the built-in roles and policies defined by Nano. Controllers may be decorated with the AuthorizeAttribute
, and allow to override the default authorization and use custom defined roles and policies.
See Security - Authorization for further details about authorization.
When deriving a controller implementation from BaseController
, model validation is automatically enabled. Based on the annotations (attributes) which model properties is decorated with. When a model fails validation, a bad request with the validation errors is returned.
Other than that, then validation isn't any different from normal.
See the official Microsoft documentation here: Model Validation Documentation
When an exception or other errors occurs for a request, and 500 Internal Server Error
is returned to the client, contain Error
response, as shown below.
public class Error
{
public virtual string Summary { get; set; } // Summary of the error.
public virtual string[] Exceptions { get; set; } // Array of exceptions.
public virtual int StatusCode { get; set; } // The http status code.
public virtual bool IsTranslated { get; set; } // Indicates if the exception messages is translated.
public virtual bool IsCoded { get; set; } // Indicates if the exception messages is coded.
}
If Error.IsTranslated
is true, then the consumer can expect the Exceptions to be translated to the language matching the Current CultureInfo, unless translations in that language is not available, and the default translation is used.
If Error.IsCoded
is true, then the consumer can expect the Exceptions to be a code, that can be used to map an error message for the user.
Several security configuration options allows for detailed control over the security setup of the application.
First, by specifying a https port, will enable secure socket layer communication. Also a certificate path and password must be specified in the configuration, in order to have a valid security protocol enabled. If the application should only support secure connections, configuring the https redirect option, will redirect traditional insecure http requests to the https protocol.
Additionally, the configuration supports various options, for controlling transport-security, XXS-protection, cache control, as well as content-type and download restrictions. Check out the Web Section of the configuration for detailed on how to enable the supported security protocols.
Nano supports the built in methods for specifying the timezone when invoking requests.
See the official documentation about timezone here: TimeZone Documentation
Nano supports virus scan by specifying a network connection to a clamav instance.
All uploaded files will be scanned, and a VirusScanException
will be thrown if one or more files contains any virus or malware.
See the official documentation about virus scan here: Virus Scan Documentation
Nano supports the built in methods for specifying the language when invoking requests.
See the official Microsoft documentation about localization here: Localization Documentation
When documentation is enabled in the configuration file, a web-interface documenting the service, it's endpoints and it's models - is created and deployed.
The documentation is based on Swashbuckle.AspNetCore.
During application startup, Nano registers dependencies for enabling api versioning. Obviously, since most controller actions will be inherited from one or more of the base controller implementations, versioning has to be annotated in derived controller classes. Additionally, versioned action methods must be overridden in the derived controller, as the versioning would otherwise apply to all derived controller implementations.
Clients can specify the version in the following ways:
- Route segment (
vx
) - Query parameter (
api-version
) - Http header (
X-Api-Version
)
Besides that, versioning follows the standard .Net Core approach.
See the official Microsoft documentation here: Versioning Documentation
During application startup, Nano initializes middleware that adds custom headers to all action responses.
The custom headers is listed below.
-
RequestId
(a unique trace identifier of the request, added to all logging context)
Additionally, headers related to authentication is appended as well, but may differ depending on the chosen security scheme.
Nano supports several different formats (listed below) for the requests and responses of the controller actions.
The format, also known as content-type may be specified, either through the Content-Type
or Accept
header, or by appending the following querystring parameter: ?format={format}
. The later is default by (Microsoft Formatting), by any of the three methods will work with Nano.
- Json
Nano has a custom contract serializer implementation.
The serializer derives from the regular implementation, but removes empty lists and system properties, related to soft-deletion and lazy-loading for instance. The serializer applies to deserializing incoming requests, though this process does nothing out of the ordinary. It also applies when serializing models into response content.
var settings = new JsonSerializerSettings
{
MaxDepth = 128,
Culture = CultureInfo.CurrentCulture,
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
PreserveReferencesHandling = PreserveReferencesHandling.None,
ContractResolver = new EntityContractResolver()
};
When serializing responses, if lazy-loading entities is enabled in data configuration, it's disabled. This ensures that data will not be lazy fetched when the serializer navigates relational properties, but only data existing in the change-tracker will be serialized.
The serializer will not serialize navigations that is of type IEntity
, except when they are annotated with IncludeAttribute
. This is to avoid returning unwanted navigation references, that is automatically added if dependent navigations are loaded separately.
When enabling health-checks in the web section of the confiugration, the application will be configured with a health-check. The health status of the application, can be found here:
http://{host}:{port}/healthz
If the health check UI is also enabled in the confiugration, an interface for monitoring the health of the application, as well as any enabled health checks for dependent providers, can be found here:
http://{host}:{port}/healthz-ui