|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Web;
using System.Web.Script.Serialization;
using System.IO;
using System.ComponentModel;
namespace App.Utilities.Web.Handlers
{
public class AjaxCallSignature
{
public AjaxCallSignature(HttpContext context)
{
args = new Dictionary<string, object>();
method = string.Empty;
string nullKeyParameter = context.Request.QueryString[null];
if (string.IsNullOrEmpty(nullKeyParameter))
{
if (!string.IsNullOrEmpty(context.Request.QueryString.ToString()) && context.Request.QueryString.ToString().StartsWith("{"))
{
}
}
if (context.Request.RequestType.ToUpper() == "POST")
{
string[] requestParams = context.Request.Params.AllKeys;
foreach (var item in requestParams)
{
if (item.ToLower() == "method")
{
method = context.Request.Params[item];
}
else if (item.ToLower().StartsWith("args["))
{
string key = item.Trim().TrimEnd(']').Substring(5);
string value = context.Request.Params[item];
args.Add(key, value);
}
else
{
string key = item;
string value = context.Request.Params[item];
args.Add(key, value);
}
}
}
else if (context.Request.RequestType.ToUpper() == "GET")
{
// evaluate the data passed as json
if (!string.IsNullOrEmpty(nullKeyParameter))
{
if (nullKeyParameter.ToLower() == "help")
{
method = "help";
return;
}
else
{
object json = null;
JavaScriptSerializer serializer = new JavaScriptSerializer();
json = serializer.DeserializeObject(context.Request.QueryString[null]);
try
{
Dictionary<string, Object> dict = (Dictionary<string, Object>)json;
if (dict.ContainsKey("method"))
method = dict["method"].ToString();
else
throw new Exception("Invalid BaseHandler call. MethodName parameter is mandatory in json object.");
if (dict.ContainsKey("returntype"))
returnType = dict["returntype"].ToString();
if (dict.ContainsKey("args"))
args = (Dictionary<string, Object>)dict["args"];
else
args = new Dictionary<string, object>();
}
catch
{
throw new InvalidCastException("Unable to cast json object to AjaxCallSignature");
}
}
}
// evaluate data passed as querystring params
foreach (string key in context.Request.QueryString.Keys)
{
if (key == null)
continue;
if (key.ToLower() == "method")
{
if (string.IsNullOrEmpty(method))
{
method = context.Request.QueryString[key];
}
else
{
throw new Exception("Method name was already specified on the json data. Specify the method name only once, either on QueryString params or on the json data.");
}
}
else if (key.ToLower() == "returncontenttype")
{
returnType = context.Request.QueryString[key];
}
if (key.ToLower().StartsWith("args["))
{
string _key = key.Trim().Substring(5).TrimEnd(']').Replace("][", "+");
args.Add(_key, context.Request.QueryString[key]);
}
else
{
args.Add(key, context.Request.QueryString[key]);
}
}
}
}
public string method { get; set; }
public string returnType { get; set; }
public Dictionary<string, object> args { get; set; }
public object Invoke(object obj, HttpContext context)
{
MethodInfo m = obj.GetType().GetMethod(method);
List<object> a = new List<object>();
if (m == null)
{
if (method.ToLower() == "help")
{
m = obj.GetType().BaseType.GetMethod("Help");
}
else
{
throw new Exception(string.Format("Method {0} not found on Handler {1}.", method, this.GetType().ToString()));
}
}
else
{
// security validation: Search for RequireAuthenticationAttribute on the method
// value=true the user must be authenticated (only supports FromsAuthentication for now
// value=false invoke the method
object[] attrs = m.GetCustomAttributes(typeof(RequireAuthenticationAttribute), true);
if (attrs != null && attrs.Length > 0)
{
if (!context.Request.IsAuthenticated && ((RequireAuthenticationAttribute)attrs[0]).RequireAuthentication)
{
throw new InvalidOperationException("Method [" + m.Name + "] Requires authentication");
}
}
}
foreach (var param in m.GetParameters())
{
/* Handle class arguments (things like custome classes and such) */
if (param.ParameterType.IsClass && !param.ParameterType.Equals(typeof(String)))
{
var argumentObject = Activator.CreateInstance(param.ParameterType);
var objectProperties = args.Keys.ToList().FindAll(k => k.StartsWith(param.Name + "+"));
foreach (var p in objectProperties)
{
string propertyName = p.Split('+')[1];
argumentObject.GetType().GetProperty(propertyName).SetValue(argumentObject, args[p], null);
}
a.Add(argumentObject);
}
/* Handle everything else (like rimitive types and strings) */
else if (args.Keys.Contains(param.Name))
{
// its usual to pass an empty json string property but casting it to certain types will throw an exception
if (string.IsNullOrEmpty(args[param.Name].ToString()) || args[param.Name].ToString() == "null" || args[param.Name].ToString() == "undefined")
{
// handle numerics. convert null or empty input values to 0
if (param.ParameterType.Equals(typeof(System.Int16)) || param.ParameterType.Equals(typeof(System.Int32)) ||
param.ParameterType.Equals(typeof(System.Int64)) || param.ParameterType.Equals(typeof(System.Decimal)) ||
param.ParameterType.Equals(typeof(System.Double)) || param.ParameterType.Equals(typeof(System.Byte)))
{
args[param.Name] = 0;
}
else if (param.ParameterType.Equals(typeof(System.Guid)))
{
args[param.Name] = new Guid();
}
else if (param.ParameterType.IsGenericType && param.ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
args[param.Name] = null;
}
}
// evaluate special types that are not directly casted from string
TypeConverter conv = TypeDescriptor.GetConverter(param.ParameterType);
if (args[param.Name] == null || param.ParameterType == args[param.Name].GetType())
{
a.Add(args[param.Name]);
}
else
{
a.Add(conv.ConvertFromInvariantString(args[param.Name].ToString()));
}
}
else
{
a.Add(null); // if there are missing arguments try passing null
}
}
return m.Invoke(obj, a.ToArray());
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.