public void Initialize(Func <Type, object> factory) { var defaultSerializer = GetResponseSerializer(DefaultSerializerType); var defaultDeserialzer = GetRequestDeserializer(DefaultDeserializerType); object serviceInstance = this; if (GetType() == typeof(Service)) { if (factory == null) { var constructor = DeclaringType.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new ServiceBuilderException( "The '" + DeclaringType.DisplayName() + "' service is invalid. You " + "must either supply a factory method, provide a default public constructor, or inherit from " + GetType().DisplayName()); } serviceInstance = constructor.Invoke(null); } else { serviceInstance = factory(DeclaringType); } } var clientScript = new StringBuilder(); clientScript.AppendLine("return {"); var firstEndpoint = true; var methods = serviceInstance.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var method in methods) { EndpointAttribute endpointAttribute = null; var parameterAttributes = new List <EndpointParameterAttribute>(); foreach (var attribute in method.GetCustomAttributes(false)) { if (attribute is EndpointAttribute) { endpointAttribute = (EndpointAttribute)attribute; } else if (attribute is EndpointParameterAttribute) { parameterAttributes.Add((EndpointParameterAttribute)attribute); } } if (endpointAttribute != null) { if (method.ReturnType != typeof(void)) { throw new ServiceBuilderException( "The '" + method.Name + "' endpoint of the '" + Name + "' service has a return type, but it should have a return type of 'void'"); } var methodParameters = method.GetParameters(); if (methodParameters.Length == 0 || methodParameters[0].ParameterType != typeof(IEndpointRequest)) { throw new ServiceBuilderException( "The '" + method.Name + "' endpoint of the '" + Name + "' service has the wrong parameter list, the first parameter must be " + "of type '" + typeof(IEndpointRequest).DisplayName() + "'"); } var parameterNames = new string[methodParameters.Length]; if (methodParameters.Length > 1) { for (var i = 1; i < methodParameters.Length; i++) { var methodParameter = methodParameters[i]; EndpointParameterAttribute endpointParameterAttribute = null; foreach (var attribute in methodParameter.GetCustomAttributes(false)) { endpointParameterAttribute = attribute as EndpointParameterAttribute; if (endpointParameterAttribute != null) { if (string.IsNullOrEmpty(endpointParameterAttribute.ParameterName)) { endpointParameterAttribute.ParameterName = methodParameter.Name; } if (endpointParameterAttribute.ParserType == null) { endpointParameterAttribute.ParserType = methodParameter.ParameterType; } break; } } if (endpointParameterAttribute == null) { endpointParameterAttribute = new EndpointParameterAttribute { ParameterName = methodParameter.Name, ParameterType = EndpointParameterType.QueryString, ParserType = methodParameter.ParameterType }; } parameterAttributes.Add(endpointParameterAttribute); parameterNames[i] = endpointParameterAttribute.ParameterName; } } var path = method.Name.ToLower(); if (!string.IsNullOrEmpty(endpointAttribute.UrlPath)) { path = endpointAttribute.UrlPath; } var relativePath = !path.StartsWith("/"); if (relativePath) { path = BasePath + path; } var m = method; Action <IEndpointRequest> action; if (methodParameters.Length == 1) { action = r => m.Invoke(serviceInstance, new[] { r }); } else { action = r => { var parameters = new object[parameterNames.Length]; parameters[0] = r; for (var i = 1; i < parameterNames.Length; i++) { parameters[i] = r.GetParameter(parameterNames[i]); } m.Invoke(serviceInstance, parameters); } }; var httpMethods = endpointAttribute.Methods ?? Methods; var endpoint = new ServiceEndpoint( path, httpMethods, action, m, endpointAttribute.ScenarioName, endpointAttribute.Analytics, _serviceDependenciesFactory.DataCatalog, _serviceDependenciesFactory.DataDependencyFactory, _serviceDependenciesFactory.RequestRouter) { RequestDeserializer = endpointAttribute.RequestDeserializer == null ? defaultDeserialzer : GetRequestDeserializer(endpointAttribute.RequestDeserializer), ResponseSerializer = endpointAttribute.ResponseSerializer == null ? defaultSerializer : GetResponseSerializer(endpointAttribute.ResponseSerializer), }; AddAnalysable(endpoint); var runable = (IRunable)endpoint; runable.Name = method.Name; runable.AllowAnonymous = AllowAnonymous; runable.CacheCategory = CacheCategory; runable.CachePriority = CachePriority; runable.Package = Package; if (endpointAttribute.RequiredPermission == null) { if (!string.IsNullOrEmpty(RequiredPermission)) { runable.RequiredPermission = RequiredPermission; if (EndpointSpecificPermission) { runable.SecureResource = Name + "/" + runable.Name; } } } else { runable.RequiredPermission = endpointAttribute.RequiredPermission; } foreach (var parameter in parameterAttributes) { var parameterParser = GetParameterParser(parameter.ParserType); endpoint.AddParameter(parameter.ParameterName, parameter.ParameterType, parameterParser); } Register(endpoint, httpMethods, relativePath, endpointAttribute.ScenarioName); if (!firstEndpoint) { clientScript.AppendLine(" },"); } firstEndpoint = false; var queryStringParameters = parameterAttributes .Where(p => (p.ParameterType & EndpointParameterType.QueryString) == EndpointParameterType.QueryString) .Select(p => p.ParameterName) .ToList(); var pathParameters = parameterAttributes .Where(p => (p.ParameterType & (EndpointParameterType.PathSegment | EndpointParameterType.QueryString)) == EndpointParameterType.PathSegment) .Select(p => p.ParameterName) .ToList(); var headerParameters = parameterAttributes .Where(p => (p.ParameterType & (EndpointParameterType.Header | EndpointParameterType.PathSegment | EndpointParameterType.QueryString)) == EndpointParameterType.Header) .Select(p => p.ParameterName) .ToList(); var formParameters = parameterAttributes .Where(p => (p.ParameterType & (EndpointParameterType.FormField | EndpointParameterType.Header | EndpointParameterType.PathSegment | EndpointParameterType.QueryString)) == EndpointParameterType.FormField) .Select(p => p.ParameterName) .ToList(); var methodName = char.ToLower(method.Name[0]) + method.Name.Substring(1); clientScript.AppendLine(" " + methodName + ": function(params, onSuccess, onDone, onFail) {"); clientScript.AppendLine(" var request = { isSuccess: function(ajax){ return ajax.status === 200; } };"); clientScript.AppendLine(" if (params != undefined && params.body != undefined) request.body = params.body;"); if (pathParameters.Count > 0) { var url = "\"" + path.ToLower() + "\""; foreach (var parameter in pathParameters) { url = url.Replace("{" + parameter.ToLower() + "}", "\" + encodeURIComponent(params." + parameter + ") + \""); } if (url.EndsWith(" + \"\"")) { url = url.Substring(0, url.Length - 5); } if (url.StartsWith("\"\" + ")) { url = url.Substring(5); } clientScript.AppendLine(" request.url = " + url + ";"); } else { clientScript.AppendLine(" request.url = \"" + path + "\";"); } if (queryStringParameters.Count > 0) { clientScript.AppendLine(" var query = \"\";"); clientScript.AppendLine(" if (params != undefined) {"); foreach (var parameter in queryStringParameters) { clientScript.AppendLine(" if (params." + parameter + " != undefined) query += \"&" + parameter + "=\" + encodeURIComponent(params." + parameter + ");"); } clientScript.AppendLine(" }"); clientScript.AppendLine(" if (query.length > 0) request.url += \"?\" + query.substring(1);"); } if (headerParameters.Count > 0) { clientScript.AppendLine(" request.headers = ["); for (var i = 0; i < headerParameters.Count; i++) { var headerParameter = headerParameters[i]; clientScript.AppendLine(" { name: \"" + headerParameter + "\", value: params." + headerParameter + " }" + (i == headerParameters.Count - 1 ? "" : ",")); } clientScript.AppendLine(" ];"); } if (formParameters.Count > 0) { clientScript.AppendLine(" if (params != undefined) {"); clientScript.AppendLine(" var form = \"\";"); foreach (var parameter in formParameters) { clientScript.AppendLine(" if (params." + parameter + " != undefined) form += \"&" + parameter + "=\" + encodeURIComponent(params." + parameter + ");"); } clientScript.AppendLine(" if (form.length > 0) {"); clientScript.AppendLine(" request.body = form.substring(1);"); clientScript.AppendLine(" }"); clientScript.AppendLine(" }"); } clientScript.AppendLine(" if (onSuccess != undefined) request.onSuccess = function(ajax){ onSuccess(ajax.response); }"); clientScript.AppendLine(" if (onFail != undefined) request.onFail = onFail;"); clientScript.AppendLine(" if (onDone != undefined) request.onDone = onDone;"); for (var i = httpMethods.Length - 1; i >= 0; i--) { var httpMethod = httpMethods[i]; var functionCall = string.Empty; switch (httpMethod) { case Method.Get: functionCall = "ns.ajax.restModule.getJson(request)"; break; case Method.Post: functionCall = formParameters.Count > 0 ? "ns.ajax.restModule.postForm(request)" : "ns.ajax.restModule.postJson(request)"; break; case Method.Put: functionCall = formParameters.Count > 0 ? "ns.ajax.restModule.putForm(request)" : "ns.ajax.restModule.putJson(request)"; break; case Method.Delete: functionCall = "ns.ajax.restModule.sendDelete(request)"; break; } if (httpMethods.Length == 1) { clientScript.AppendLine(" " + functionCall + ";"); } else if (i == 0) { clientScript.AppendLine(" else " + functionCall + ";"); } else if (i == httpMethods.Length - 1) { clientScript.AppendLine(" if (params.method == \"" + httpMethod.ToString().ToUpper() + "\") " + functionCall + ";"); } else { clientScript.AppendLine(" else if (params.method == \"" + httpMethod.ToString().ToUpper() + "\") " + functionCall + ";"); } } } } if (!firstEndpoint) { clientScript.AppendLine(" }"); } clientScript.AppendLine("}"); ClientScript = clientScript.ToString(); } T IDebuggable.GetDebugInfo <T>(int parentDepth, int childDepth) { return(new DebugService() as T); }
IList <IEndpointDocumentation> IRequestRouter.GetEndpointDocumentation() { List <Registration> registrations; lock (_registrations) registrations = _registrations.ToList(); var endpoints = new List <IEndpointDocumentation>(); foreach (var registration in registrations.Where(r => r.TestScenarioName == null)) { var endpointDocumentation = new EndpointDocumentation { RelativePath = registration.Filter.Description }; if (registration.Router != null) { var routerEndpoints = registration.Router.GetEndpointDocumentation(); endpoints.AddRange(routerEndpoints); continue; } var documented = registration.Runable as IDocumented; if (documented != null) { endpointDocumentation.Description = documented.Description; endpointDocumentation.Examples = documented.Examples; endpointDocumentation.Attributes = documented.Attributes; } object[] customAttributes = null; if (registration.Method != null) { customAttributes = registration.Method.GetCustomAttributes(true) .Concat( registration.Method.GetParameters() .Skip(1) .Select(p => new { parameter = p, attribute = p.GetCustomAttributes(false).Select(a => a as EndpointParameterAttribute).FirstOrDefault(a => a != null) }) .Select(o => { var attribute = o.attribute; if (attribute == null) { attribute = new EndpointParameterAttribute { ParameterType = EndpointParameterType.QueryString } } ; if (string.IsNullOrEmpty(attribute.ParameterName)) { attribute.ParameterName = o.parameter.Name; } if (attribute.ParserType == null) { attribute.ParserType = o.parameter.ParameterType; } return(attribute); })) .ToArray(); } else if (registration.DeclaringType != null) { customAttributes = registration.DeclaringType.GetCustomAttributes(true); } string endpointPath = null; string queryStringExample = null; if (customAttributes != null) { foreach (var attribute in customAttributes) { var description = attribute as DescriptionAttribute; if (description != null) { endpointDocumentation.Description = endpointDocumentation.Description == null ? description.Html : (endpointDocumentation.Description + "<br>" + description.Html); } var example = attribute as ExampleAttribute; if (example != null) { endpointDocumentation.Examples = endpointDocumentation.Examples == null ? example.Html : (endpointDocumentation.Examples + "<br>" + example.Html); } var option = attribute as OptionAttribute; if (option != null) { if (endpointDocumentation.Attributes == null) { endpointDocumentation.Attributes = new List <IEndpointAttributeDocumentation>(); } endpointDocumentation.Attributes.Add(new EndpointAttributeDocumentation { Type = option.OptionType.ToString(), Name = option.Name, Description = option.Html }); } var endpoint = attribute as EndpointAttribute; if (endpoint != null) { endpointPath = endpoint.UrlPath; } var endpointParameter = attribute as EndpointParameterAttribute; if (endpointParameter != null) { if (endpointDocumentation.Attributes == null) { endpointDocumentation.Attributes = new List <IEndpointAttributeDocumentation>(); } var parameterValue = "{" + endpointParameter.ParameterName + "}"; var parameterDescription = endpointParameter.ParserType.DisplayName(); if (typeof(IDocumented).IsAssignableFrom(endpointParameter.ParserType) || typeof(IParameterParser).IsAssignableFrom(endpointParameter.ParserType)) { var constructor = endpointParameter.ParserType.GetConstructor(Type.EmptyTypes); if (constructor != null) { var parser = constructor.Invoke(null); var parameterDocumented = parser as IDocumented; var parameterParser = parser as IParameterParser; if (parameterDocumented != null) { parameterDescription = parameterDocumented.Description; parameterValue = parameterDocumented.Examples; } else if (parameterParser != null) { parameterDescription = parameterParser.Description; } } if (!string.IsNullOrEmpty((endpointParameter.Description))) { parameterDescription = endpointParameter.Description; } } if (endpointParameter.ParameterType.HasFlag(EndpointParameterType.QueryString)) { if (queryStringExample == null) { queryStringExample = "?" + endpointParameter.ParameterName + "=" + parameterValue; } else { queryStringExample += "&" + endpointParameter.ParameterName + "=" + parameterValue; } } endpointDocumentation.Attributes.Add(new EndpointAttributeDocumentation { Type = endpointParameter.ParameterType.ToString(), Name = endpointParameter.ParameterName, Description = parameterDescription }); } } } if (string.IsNullOrEmpty(endpointDocumentation.Examples) && !string.IsNullOrEmpty(endpointPath)) { endpointDocumentation.Examples = endpointPath; if (!string.IsNullOrEmpty(queryStringExample)) { endpointDocumentation.Examples += queryStringExample; } } endpoints.Add(endpointDocumentation); } return(endpoints); }