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);
        }
Exemple #2
0
        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);
        }