/// <summary>
        /// Called by the ASP.NET MVC framework before the action method executes.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        /// <exception cref="BeetleException">BeetleActionFilterAttribute should only be applied to Queryable actions.</exception>
        public override void OnActionExecuting(ActionExecutingContext filterContext) {
            base.OnActionExecuting(filterContext);

            var controller = filterContext.Controller;
            var action = filterContext.ActionDescriptor;
            var reflectedAction = action as ReflectedActionDescriptor;
            var actionMethod = reflectedAction != null 
                ? reflectedAction.MethodInfo 
                : controller.GetType().GetMethod(action.ActionName);

            var service = controller as IBeetleService;
            if (_beetleConfig == null)
                _beetleConfig = service != null ? service.BeetleConfig : BeetleConfig.Instance;

            string queryString;
            NameValueCollection queryParams;
            object[] actionArgs;
            // handle request message
            GetParameters(filterContext, out queryString, out queryParams, out actionArgs);

            // execute the action method
            var contentValue = actionMethod.Invoke(controller, actionArgs);
            // get client hash
            // process the request and return the result
            var actionContext = new ActionContext(action.ActionName, contentValue, queryString, queryParams, MaxResultCount, CheckRequestHashNullable);
            var processResult = ProcessRequest(contentValue, actionContext, service);
            // handle response message
            filterContext.Result = HandleResponse(filterContext, processResult);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="BeetleActionFilterAttribute" /> class.
 /// </summary>
 /// <param name="configType">Type of the config.</param>
 /// <exception cref="System.ArgumentException">Cannot create config instance.</exception>
 public BeetleActionFilterAttribute(Type configType = null) {
     if (configType != null) {
         _beetleConfig = Activator.CreateInstance(configType) as BeetleConfig;
         if (_beetleConfig == null)
             throw new ArgumentException(Resources.CannotCreateConfigInstance);
     }
 }
예제 #3
0
        /// <summary>
        /// Handles the request.
        /// </summary>
        /// <param name="queryString">The query string.</param>
        /// <param name="queryParams">The query parameters.</param>
        /// <param name="actionArgs">The action arguments.</param>
        /// <param name="config">The beetle configuration.</param>
        /// <param name="request">The request.</param>
        /// <param name="actionParameters">The action parameters.</param>
        /// <param name="parameters">The parameters.</param>
        /// <exception cref="BeetleException">Action must have only one parameter (JsonObject, object or dynamic) to be able called with POST.</exception>
        internal static void GetParameters(out string queryString, out NameValueCollection queryParams, out object[] actionArgs,
                                           BeetleConfig config = null, HttpRequest request = null,
                                           ParameterDescriptor[] actionParameters = null, IDictionary<string, object> parameters = null) {
            if (config == null)
                config = BeetleConfig.Instance;
            if (request == null)
                request = HttpContext.Current.Request;

            if (request.HttpMethod == "POST") {
                // supported methods can only have one parameter 
                // (MVC behavior for beetle must be same as WebApi and WebApi cannot have more than one parameters for POST)
                if (actionParameters == null || actionParameters.Length <= 1) {
                    var hasPrm = actionParameters != null && actionParameters.Length == 1;
                    object actionArg = null;
                    // read post data
                    request.InputStream.Position = 0;
                    queryString = new StreamReader(request.InputStream).ReadToEnd();
                    if (request.ContentType.Contains("application/json")) {
                        if (hasPrm)
                            actionArg = JsonConvert.DeserializeObject(queryString, config.JsonSerializerSettings) as JObject;
                        // but now there is no query string parameters, we must populate them manually for beetle queries
                        // otherwise beetle cannot use query parameters when using post method
                        var d = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(queryString);
                        queryParams = new NameValueCollection();
                        foreach (var i in d)
                            queryParams.Add(i.Key, i.Value == null ? string.Empty : i.Value.ToString());
                    }
                    else {
                        var prms = request.Params;
                        queryParams = prms;
                        var d = prms.AllKeys.ToDictionary(k => k, k => prms[k]);
                        if (hasPrm) {
                            var jsonStr = _javaScriptSerializer.Value.Serialize(d);
                            actionArg = JsonConvert.DeserializeObject(jsonStr, config.JsonSerializerSettings);
                        }
                    }
                    actionArgs = hasPrm ? new[] { actionArg } : new object[0];
                }
                else {
                    queryString = string.Empty;
                    queryParams = null;
                    actionArgs = null;
                }
            }
            else {
                queryString = request.Url.Query;
                if (queryString.StartsWith("?"))
                    queryString = queryString.Substring(1);
                queryString = queryString.Replace(":", "%3A");

                queryParams = request.QueryString;
                if (actionParameters != null && parameters != null) {
                    actionArgs = actionParameters
                        .Select(pd => parameters[pd.ParameterName])
                        .ToArray();
                }
                else
                    actionArgs = null;
            }
        }
        /// <summary>
        /// Called when [action executed].
        /// </summary>
        /// <param name="actionExecutedContext">The action executed context.</param>
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) {
            if (actionExecutedContext.Exception != null || !actionExecutedContext.Response.IsSuccessStatusCode) return;

            var request = actionExecutedContext.Request;
            var response = actionExecutedContext.Response;
            var controller = actionExecutedContext.ActionContext.ControllerContext.Controller;
            var action = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
            var service = controller as IBeetleService;

            // get query parameters
            string queryString;
            var queryParams = GetParameters(actionExecutedContext, out queryString);
            object contentValue;
            if (!response.TryGetContentValue(out contentValue)) return;

            var actionContext = new ActionContext(action, contentValue, queryString, queryParams, MaxResultCount, CheckRequestHashNullable);

            request.Properties["BeetleService"] = service;
            request.Properties["BeetleActionContext"] = actionContext;

            if (_beetleConfig == null)
                _beetleConfig = service != null ? service.BeetleConfig : BeetleConfig.Instance;

            // call base and let WebApi process the request
            base.OnActionExecuted(actionExecutedContext);

            // get the processed query from content
            if (!response.TryGetContentValue(out contentValue)) return;
            var queryable = contentValue as IQueryable;

            // apply OData parameters
            if (queryable != null)
                contentValue = FixODataQuery(queryable, request, service);

            // process the request and return the result
            var processResult = ProcessRequest(contentValue, actionContext, request, service);
            // handle response message
            response.Content = HandleResponse(actionExecutedContext, processResult);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="BeetleActionFilterAttribute"/> class.
 /// </summary>
 /// <param name="config">The configuration.</param>
 public BeetleActionFilterAttribute(BeetleConfig config) {
     _beetleConfig = config;
 }
 public BeetleQueryableAttribute(BeetleConfig config)
     : this() {
     _beetleConfig = config;
 }
예제 #7
0
        /// <summary>
        /// Handles the response.
        /// </summary>
        /// <param name="processResult">The process result.</param>
        /// <param name="config">The configuration.</param>
        /// <param name="response">The response.</param>
        /// <returns></returns>
        internal static ObjectContent HandleResponse(ProcessResult processResult, BeetleConfig config = null, HttpResponse response = null) {
            if (config == null)
                config = BeetleConfig.Instance;
            if (response == null)
                response = HttpContext.Current.Response;

            var type = processResult.Result == null
                ? typeof(object)
                : processResult.Result.GetType();
            var retVal = new ObjectContent(type, processResult.Result, config.MediaTypeFormatter);

            // set InlineCount header info if exists
            object inlineCount = processResult.InlineCount;
            if (inlineCount != null && response.Headers["X-InlineCount"] == null)
                response.Headers["X-InlineCount"] = inlineCount.ToString();
            if (processResult.UserData != null && response.Headers["X-UserData"] == null) {
                var userDataStr = JsonConvert.SerializeObject(processResult.UserData, config.JsonSerializerSettings);
                response.Headers["X-UserData"] = userDataStr;
            }

            return retVal;
        }
예제 #8
0
        /// <summary>
        /// Handles the response.
        /// </summary>
        /// <param name="processResult">The process result.</param>
        /// <param name="config">The configuration.</param>
        /// <param name="response">The response.</param>
        /// <returns></returns>
        internal static ActionResult HandleResponse(ProcessResult processResult, BeetleConfig config = null, HttpResponse response = null) {
            var result = processResult.Result;

            if (config == null)
                config = BeetleConfig.Instance;
            if (response == null)
                response = HttpContext.Current.Response;

            // set InlineCount header info if exists
            object inlineCount = processResult.InlineCount;
            if (inlineCount != null && response.Headers["X-InlineCount"] == null)
                response.Headers.Add("X-InlineCount", inlineCount.ToString());
            if (processResult.UserData != null && response.Headers["X-UserData"] == null) {
                var userDataStr = JsonConvert.SerializeObject(processResult.UserData, config.JsonSerializerSettings);
                response.Headers.Add("X-UserData", userDataStr);
            }

            var actionResult = result as ActionResult;
            if (actionResult != null) return actionResult;

            // write the result to response content
            return new BeetleJsonResult(config, processResult) {
                Data = result,
                ContentEncoding = response.HeaderEncoding,
                ContentType = "application/json",
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }