UNPKG

dotnode

Version:

.NET-like MVC framework for Node.js

244 lines (170 loc) 6.57 kB
var BaseController = require('../controllers/controller'), Injector = require('../ioc/injector'), ActionResult = require('../models/actionResult'), resultTypes = require('../models/actionResultType'), ViewEngine = require('../views/viewEngine'), UrlHelper = require('../routes/urlHelper'), IDeferred = require('../models/iDeferred'), extend = require('xtend'); var ControllerFactory = function (appContext) { this._controllers = {}; this._appContext = appContext; this._viewEngine = new ViewEngine(); this._injector = new Injector(); }; // #region private methods ControllerFactory.prototype._handleResultSync = function (result, contextOptions) { if (result instanceof ActionResult) { this._handleActionResult(result, contextOptions); } return result; }; ControllerFactory.prototype._handleResultAsync = function (result, contextOptions) { var invokeOptions = { request: contextOptions.request, response: contextOptions.response }; result.invoke(invokeOptions); return result; }; ControllerFactory.prototype._handleActionResult = function (result, options) { switch (result.type) { case resultTypes.viewResult: { this._handleViewResult(result, options); break; } case resultTypes.jsonResult: { this._handleJsonResult(result, options); break; } default: { break; } } }; ControllerFactory.prototype._handleViewResult = function (result, options) { var viewData = result.data; var renderingOptions = extend(options, { viewName: viewData.viewName, model: viewData.model, viewOptions: viewData.viewOptions, controllerContext: options.controllerContext }); this._viewEngine.render(renderingOptions); }; ControllerFactory.prototype._handleJsonResult = function (result, options) { var jsonData = result.data, json = jsonData.object, response = options.response; response.writeHead(200, { 'Content-Type': 'application/json' }); response.end(JSON.stringify(json)); }; // #endregion ControllerFactory.prototype.registerController = function (controllerName, Controller) { if (typeof this._controllers[controllerName] == 'function') { throw 'Controller with name ' + controllerName + ' already registered'; } this._controllers[controllerName] = Controller; }; ControllerFactory.prototype.registerControllers = function (controllers) { for (var name in controllers) { if (controllers.hasOwnProperty(name)) { this.registerController(name, controllers[name]); } } }; ControllerFactory.prototype.controllerIsRegistered = function (controllerName) { return typeof this._controllers[controllerName] == 'function'; }; ControllerFactory.prototype.invoke = function (options) { var actionName = options.actionName, controllerName = options.controllerName, areaName = options.areaName, params = options.params, request = options.request, response = options.response; var Controller = this._controllers[controllerName]; Controller.prototype = extend({}, BaseController.prototype, Controller.prototype); var controllerInstance = new Controller(); controllerInstance.request = request; controllerInstance.response = response; var controllerContext = { actionName: actionName, controllerName: controllerName, areaName: areaName, request: request, response: response, viewBag: controllerInstance.viewBag }; controllerInstance.url = new UrlHelper(this._appContext, controllerContext); controllerContext.url = controllerInstance.url; controllerInstance.controllerContext = controllerContext; var action = Controller.prototype[actionName]; if (typeof action != 'function') { throw 'Requested action is not a function'; } var result = this._injector.invoke(action, controllerInstance, params); if(typeof result == 'undefined'){ return; } controllerContext.viewBag = controllerInstance.viewBag; controllerContext.pageOptions = controllerInstance.pageOptions; var contextOptions = { request: request, response: response, actionName: actionName, controllerName: controllerName, areaName: areaName, controllerContext: controllerContext, controllerInstance: controllerInstance }; if (result instanceof IDeferred) { return this._handleResultAsync(result, contextOptions); } else { return this._handleResultSync(result, contextOptions); } }; ControllerFactory.prototype.getVerbs = function (actionName, controllerName) { var allVerbs = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'CONNECT']; var Controller = this._controllers[controllerName]; if (typeof Controller != 'function') { throw 'Controller ' + controllerName + ' is not registered'; } var config = Controller.config; if (typeof config == 'undefined') { return allVerbs; } if (typeof config.attributes == 'undefined') { return allVerbs; } var attributes = config.attributes[actionName]; if (!attributes) { return allVerbs; } var specifiedVerbs = [], ignoredVerbs = []; for (var name in attributes) { var invariantName = name.replace(/w+/g, '').toUpperCase(); if (attributes.hasOwnProperty(name) && (allVerbs.indexOf(invariantName) != -1)) { if (attributes[name]) { specifiedVerbs.push(invariantName); } else { ignoredVerbs.push(invariantName); } } } if (specifiedVerbs.length == 0 && ignoredVerbs.length == 0) { return allVerbs; } var acceptedVerbs = []; for (var i in specifiedVerbs) { if (ignoredVerbs.indexOf(specifiedVerbs[i]) != -1) { acceptedVerbs.push(specifiedVerbs[i]); } } return specifiedVerbs; }; module.exports = ControllerFactory;