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; }
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())); } } }
public Endpoint BuildEndpoint(string methodName, EndpointAttribute attribute) { return(new Endpoint() { EndpointId = attribute.EndpointId, DisplayName = attribute.DisplayName, Description = attribute.Description, IsList = attribute.IsList, Method = methodName }); }
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; }