Esempio n. 1
0
        public UriHandler(Regex matcher, IEnumerable <string> parameterNames, object responder, MethodInfo endpoint,
                          EndpointAttribute endpointAttribute)
        {
            if (matcher == null)
            {
                throw new ArgumentNullException(nameof(matcher));
            }
            if (parameterNames == null)
            {
                throw new ArgumentNullException(nameof(parameterNames));
            }
            if (responder == null)
            {
                throw new ArgumentNullException(nameof(responder));
            }
            if (endpoint == null)
            {
                throw new ArgumentNullException(nameof(endpoint));
            }
            if (endpointAttribute == null)
            {
                throw new ArgumentNullException(nameof(endpointAttribute));
            }

            Matcher           = matcher;
            ParameterNames    = new List <string>(parameterNames);
            Responder         = responder;
            Endpoint          = endpoint;
            EndpointAttribute = endpointAttribute;
        }
Esempio n. 2
0
        static ResponseManager()
        {
            _endpointToResponseMap = new Dictionary <Endpoint, List <ResponseMatch> >();

            Assembly assembly = typeof(IResponse).GetTypeInfo().Assembly;

            foreach (Type responseType in assembly.ExportedTypes.Where(x => x.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IResponse))))
            {
                EndpointAttribute endpointAttribute =
                    responseType.GetTypeInfo().GetCustomAttributes(typeof(EndpointAttribute), false)
                    .OfType <EndpointAttribute>()
                    .FirstOrDefault();
                if (endpointAttribute != null)
                {
                    List <ResponseMatch> responseMatches;
                    if (_endpointToResponseMap.TryGetValue(endpointAttribute.Endpoint, out responseMatches) == false)
                    {
                        _endpointToResponseMap.Add(endpointAttribute.Endpoint,
                                                   responseMatches = new List <ResponseMatch>());
                    }

                    //TODO: What happens if there is not a default constructor? multiple constructors?
                    Expression body = Expression.New(responseType);
                    var        func = (Func <IResponse>)Expression.Lambda(body).Compile();

                    responseMatches.Add(new ResponseMatch(func, endpointAttribute.GetPredicate()));
                }
            }
        }
Esempio n. 3
0
 public Endpoint BuildEndpoint(string methodName, EndpointAttribute attribute)
 {
     return(new Endpoint()
     {
         EndpointId = attribute.EndpointId,
         DisplayName = attribute.DisplayName,
         Description = attribute.Description,
         IsList = attribute.IsList,
         Method = methodName
     });
 }
Esempio n. 4
0
        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);
        }
        /// <summary>
        /// Setup service for given config
        /// </summary>
        /// <param name="contract">Contract type of the host</param>
        /// <param name="config">Config of component</param>
        public void Setup(Type contract, HostConfig config)
        {
            // Create base address depending on chosen binding
            string protocol;

            switch (config.BindingType)
            {
            case ServiceBindingType.NetTcp:
                protocol = "net.tcp";
                break;

            default:
                protocol = "http";
                break;
            }

            // Create service host
            _service           = _factory.CreateServiceHost(contract);
            _contract          = contract;
            _endpointAttribute = _contract.GetCustomAttribute <EndpointAttribute>();

            // Configure host
            _service.CloseTimeout = TimeSpan.Zero;

            // Set binding
            Binding binding;

            switch (config.BindingType)
            {
            case ServiceBindingType.BasicHttp: binding = BindingFactory.CreateBasicHttpBinding(config.RequiresAuthentification);
                break;

            case ServiceBindingType.NetTcp: binding = BindingFactory.CreateNetTcpBinding(config.RequiresAuthentification);
                break;

            default: binding = BindingFactory.CreateWebHttpBinding();
                break;
            }

            // Set default timeouts
            binding.OpenTimeout = _portConfig.OpenTimeout != PortConfig.InfiniteTimeout
                ? TimeSpan.FromSeconds(_portConfig.OpenTimeout)
                : TimeSpan.MaxValue;

            binding.CloseTimeout = _portConfig.CloseTimeout != PortConfig.InfiniteTimeout
                ? TimeSpan.FromSeconds(_portConfig.CloseTimeout)
                : TimeSpan.MaxValue;

            binding.SendTimeout = _portConfig.SendTimeout != PortConfig.InfiniteTimeout
                ? TimeSpan.FromSeconds(_portConfig.SendTimeout)
                : TimeSpan.MaxValue;

            binding.ReceiveTimeout = _portConfig.ReceiveTimeout != PortConfig.InfiniteTimeout
                ? TimeSpan.FromSeconds(_portConfig.ReceiveTimeout)
                : TimeSpan.MaxValue;

            // Create endpoint address from config
            var port = config.BindingType == ServiceBindingType.NetTcp ? _portConfig.NetTcpPort : _portConfig.HttpPort;

            // Override binding timeouts if necessary
            if (config is ExtendedHostConfig extendedConfig && extendedConfig.OverrideFrameworkConfig)
            {
                // Override binding timeouts if necessary
                port = extendedConfig.Port;
                binding.OpenTimeout = extendedConfig.OpenTimeout != PortConfig.InfiniteTimeout
                    ? TimeSpan.FromSeconds(extendedConfig.OpenTimeout)
                    : TimeSpan.MaxValue;

                binding.CloseTimeout = extendedConfig.CloseTimeout != PortConfig.InfiniteTimeout
                    ? TimeSpan.FromSeconds(extendedConfig.CloseTimeout)
                    : TimeSpan.MaxValue;

                binding.SendTimeout = extendedConfig.SendTimeout != PortConfig.InfiniteTimeout
                    ? TimeSpan.FromSeconds(extendedConfig.SendTimeout)
                    : TimeSpan.MaxValue;

                binding.ReceiveTimeout = extendedConfig.ReceiveTimeout != PortConfig.InfiniteTimeout
                    ? TimeSpan.FromSeconds(extendedConfig.ReceiveTimeout)
                    : TimeSpan.MaxValue;
            }

            _endpointAddress = $"{protocol}://{_portConfig.Host}:{port}/{config.Endpoint}/";

            var endpoint = _service.AddServiceEndpoint(contract, binding, _endpointAddress);

            // Add  behaviors
            endpoint.Behaviors.Add(new CultureBehavior());

            if (config.BindingType == ServiceBindingType.WebHttp)
            {
                endpoint.Behaviors.Add(new WebHttpBehavior());
                endpoint.Behaviors.Add(new CorsBehaviorAttribute());
            }

            if (config.MetadataEnabled)
            {
                var serviceMetadataBehavior = new ServiceMetadataBehavior
                {
                    HttpGetEnabled = true,
                    HttpGetUrl     = new Uri($"http://{_portConfig.Host}:{_portConfig.HttpPort}/Metadata/{config.Endpoint}")
                };
                _service.Description.Behaviors.Add(serviceMetadataBehavior);
            }

            if (config.HelpEnabled)
            {
                var serviceDebugBehavior = _service.Description.Behaviors.Find <ServiceDebugBehavior>();
                serviceDebugBehavior.IncludeExceptionDetailInFaults = true;
                serviceDebugBehavior.HttpHelpPageEnabled            = true;
                serviceDebugBehavior.HttpHelpPageUrl = new Uri($"http://{_portConfig.Host}:{_portConfig.HttpPort}/Help/{config.Endpoint}");
            }

            _hostConfig = config;
        }