System Parameters
There are three system parameters that RoutingMiddleware supports and have a special meaning:
-
{controller}: This parameter defines a logical name by which a group of controller stored procedures are targeted. It denotes a logical controller that does the job, not a physical object.
-
{action}: This parameter defines the action that the final controller should carry out in order to fulfill current request.
-
{area}: This parameter is a logical name that defines an area or group that the controller belongs to. This provides the ability to have controllers with the same name that control different parts of the application.
These system parameters participate actively in determining name of the controller stored-procedure that will be invoked in the next step of request pipeline by MvcMiddleware (or any middleware that is responsible for invoking controller stored procedure).
If RoutingMiddleware finds a route match, it adds two more system parameters named $route_id and $route_sproc to route values dictionary. $route_id is the [id] of matched route and $route_sproc is the name of controller stored procedure that should satisfy the response.
Determining name of the controller stored-procedure will be explained later in Routing and name of controller SPROC section.
Optional Parameters
Optional parameters are defined using a question mark at the end of their name as in {controller?}. When a parameter is optional, their equivalent segment in the given URL could be missing.
Example:
/product/{action?}
The above route matches /product in addition to /product/list, /product/show, /product/edit that the previous route (i.e. /product/{action} could accept).
Http Method Constraint
Using httpMethods field we can specify http method constraint i.e. specify a list of http methods that the route will match only when the request is sent with one of them. Value of this field should be a JSON array.
Example:
| route |
httpMethods |
/{controller}/{action}
|
[ "GET", "POST" ]
|
Here, the above route will only match with a URL like /product only when the request is sent using GET or POST method. If the request is sent using say PUT method the route will not match.
Global Mapping
There is a global setting named Chameleon.Routing.HttpMethodAsAction in chameleon.Settings table that enacts http method to action mapping. There is also a global setting named Chameleon.Routing.HttpMethodMapping that defines how http method should be mapped to actions. Here is an example:
| route |
/{controller}/{action?}
|
The default value for global Chameleon.Routing.HttpMethodMapping setting is as follows:
{ "post": "insert", "put":"update", "delete": "delete", "get": "get" }
Now, if current URL misses a value for action parameter (e.g. current URL is /product) and the request is sent using say a POST method, RoutingMiddleware will uses insert for the value of action parameter.
If no value is found in global Chameleon.Routing.HttpMethodMapping setting for current http method, RoutingMiddleware will use the http verb itself for the value of action parameter. For example, if current URL is /product and it is sent using a PATCH method, the value for action parameter will be patch (in lowercase).
Chameleon.Routing.HttpMethodAsAction is true (1) by default.
Note: The defaults field takes precendence over global http method to action mapping. If a default value for action parameter is specified in defaults (like { "action": "index" }), the final value for action parameter will be index.
Local Mapping
Sometimes we may want to override global http mapping. We can specify desired http mapping value in the httpMethods for any http verb we want. Look at the following example:
| route |
httpMethods |
/{controller}/{action?}
|
[ "GET", { "POST": "add" }, { "PUT": "edit" } ]
|
Here, the route will only match for requests sent in GET, POST and PUT. Now, if the request misses a value for action (the URL is e.g. /product), RoutingMiddleware will use add if it is sent in POST or will use edit if it is sent in PUT.
Pay attention that, local http method mapping has more priority over defaults. Look at the following example:
| route |
defaults |
httpMethods |
/{controller}/{action}
|
{ "action": "index" }
|
[ "GET", { "POST": "add" }, { "PUT": "edit" } ]
|
Here, if the request URL is /product and it is sent using GET method, the value for action will be index since no override value for GET is defined. However, if the request is sent using POST, the add value takes precedence over the default index value. So, the value of action parameter will be add.
As it was stated in System Parameters section, action plays a primary role in determining name of controller stored-procedure. This is explained in Controller Factory section.
Disable http mapping locally
In some situations, we may want to disable http method mapping for a specific route. As it was said, http method mapping is globally active. Thus, if action parameter has no value and no default value for action is specified, RoutingMiddleware will go for global http method mapping. We can prevent this in a specific route by a setting named httpMethodAsAction with a false or 1 value in route's settings. Look at the following example:
| route |
defaults |
settings |
/{controller}/{action?}
|
|
{ "httpMethodAsAction": false }
|
If current URL is /product, the final value for action will be an empty string. In fact no value for action will be set. This enables us to have a single controller stored-procedure for any http method the request is sent with. Note that, in order for this feature to work, we should not specify a default value for action in the defaults, otherwise, the default value will be used for action.