/// <summary> /// Invokes the service method. /// </summary> /// <param name="handler">The REST handler associated with the HTTP request.</param> /// <param name="service">The service instance.</param> /// <param name="method">The service method.</param> /// <returns>A task that invokes the service method.</returns> public virtual Task InvokeAsync(IRestServiceHandler handler, object service, MethodInfo method) { if (service == null || method == null) { throw new HttpResponseException(HttpStatusCode.NotFound, Resources.Global.MismatchedServiceMethod); } if (handler == null) { throw new HttpResponseException(HttpStatusCode.InternalServerError, Resources.Global.MissingRouteHandler); } if (handler.Context == null) { throw new HttpResponseException(HttpStatusCode.InternalServerError, Resources.Global.MissingServiceContext); } List<IServiceBehavior> behaviors = GetServiceMethodBehaviors(handler, service, method); AddServiceBehaviors(method, behaviors); LogUtility.LogRequestData(handler.Context.GetHttpContext()); object returnedObject = InvokeWithBehaviors(handler, service, method, behaviors); Task invocationTask = CreateResultTask(handler, returnedObject, method.ReturnType); LogUtility.LogResponseData(handler.Context.GetHttpContext()); return invocationTask; }
/// <summary> /// Creates a parameter value based on the routing and HTTP data. /// </summary> /// <param name="handler">The REST handler associated with the HTTP request.</param> /// <param name="parameter">The service method parameters.</param> /// <param name="isResource"> /// true if the parameter represents a REST resource; otherwise, false. Only 1 resource per /// service method is allowed. /// </param> /// <returns>The created parameter value.</returns> public virtual object CreateValue(IRestServiceHandler handler, ParameterInfo parameter, out bool isResource) { if (handler == null) { throw new ArgumentNullException("handler"); } if (parameter == null) { throw new ArgumentNullException("parameter"); } IServiceContext context = handler.Context; ITypeBinder typeBinder = GetParameterBinder(parameter); if (typeBinder is DoNotBindAttribute) { isResource = false; return null; } if (typeBinder != null) { isResource = IsResourceParameter(context, parameter); return GetTypeBindedValue(context, parameter, typeBinder); } object routeValue = TryGetRouteValue(parameter, context.Request.RouteValues); if (routeValue != null) { isResource = false; return routeValue; } if (IsResourceParameter(context, parameter)) { isResource = true; return GetResourceValue(handler, parameter); } isResource = false; if (typeof(IRestContext).IsAssignableFrom(parameter.ParameterType)) { return Rest.Configuration.ServiceLocator.GetService(parameter.ParameterType); } return null; }
/// <summary> /// Locates the service method associated with the provided REST handler and returns the associated data. /// </summary> /// <param name="handler">A REST handler associated with HTTP request.</param> /// <returns>The service method data.</returns> public virtual ServiceMethodLocatorData Locate(IRestServiceHandler handler) { if (handler == null) { throw new ArgumentNullException("handler"); } var serviceContractType = GetServiceContractType(handler.ServiceContractTypeName); object service = InitializeService(serviceContractType, m_serviceContext.Request); HttpMethod httpMethod = m_serviceContext.Request.Method; if (httpMethod == HttpMethod.Head) { m_serviceContext.GetHttpContext().Response.SuppressContent = true; } MethodInfo method = GetServiceMethod(handler.ServiceUrl, serviceContractType, handler.UrlTemplate, httpMethod); return new ServiceMethodLocatorData(service, method); }
public RestServiceRouteInitializer(IRestServiceHandler handler) { m_handler = handler; }
private static List<IServiceBehavior> GetServiceMethodBehaviors(IRestServiceHandler handler, object service, MethodInfo method) { List<IServiceBehavior> behaviors = ServiceBehaviorRegistry.GetBehaviors(handler) .Where(behavior => behavior.AppliesTo(handler.Context, new MethodAppliesContext(service, method))) .ToList(); return behaviors; }
private async Task CreateResultTask(IRestServiceHandler handler, object returnedObject, Type methodReturnType) { var returnedTask = returnedObject as Task; if (returnedTask != null) { await returnedTask; var taskInfo = GetTaskInfo(returnedTask); returnedObject = taskInfo.Item1; methodReturnType = taskInfo.Item2; } if (returnedObject is IAsyncResult) { throw new InvalidOperationException(Resources.Global.InvalidIAsyncResultReturned); } var resultExecutor = new ResultExecutor(); if (methodReturnType == typeof(void)) { resultExecutor.ExecuteNoContent(handler.Context); return; } IResult result = m_resultWrapper.Wrap(handler, returnedObject, methodReturnType); await resultExecutor.Execute(result, handler.Context); }
private object[] GenerateMethodArguments(IRestServiceHandler handler, MethodInfo method, out object resource) { var methodArguments = new List<object>(); resource = null; foreach (ParameterInfo parameter in method.GetParameters()) { bool isResource; object argumentValue = m_parameterValueProvider.CreateValue(handler, parameter, out isResource); if (isResource) { resource = argumentValue; } methodArguments.Add(argumentValue); } return methodArguments.ToArray(); }
private object InvokeWithBehaviors(IRestServiceHandler handler, object service, MethodInfo method, List<IServiceBehavior> behaviors) { m_behaviorInvoker.InvokeOnAuthorizingBehaviors(behaviors.OfType<ISecureServiceBehavior>().ToList(), service, method); object resource; object[] methodArguments = GenerateMethodArguments(handler, method, out resource); if (!ReferenceEquals(null, resource)) { handler.Context.Request.ResourceBag.Resource = resource; } if (m_behaviorInvoker.InvokeOnExecutingBehaviors(behaviors, service, method, resource) == BehaviorMethodAction.Stop) { return null; } object result = method.Invoke(service, methodArguments); m_behaviorInvoker.InvokeOnExecutedBehaviors(behaviors, service, method, result); return result; }
public static void SetExceptionHandler(IRestServiceHandler handler, IServiceExceptionHandler exceptionHandler) { handlerExceptionHandlers.AddOrUpdate(handler, handlerToAdd => exceptionHandler, (handlerToUpdate, exceptionHandlerToUpdate) => exceptionHandler); }
public static IServiceExceptionHandler GetExceptionHandler(IRestServiceHandler handler) { IServiceExceptionHandler exceptionHandler; return handlerExceptionHandlers.TryGetValue(handler, out exceptionHandler) ? exceptionHandler : globalExceptionHandler; }
public static void Add(IRestServiceHandler handler) { unvalidatedHandlers.Add(handler); }
public static bool IsUnvalidated(IRestServiceHandler handler) { return unvalidatedHandlers.Contains(handler); }
/// <summary> /// Gets the resource value for the service method parameter. /// </summary> /// <param name="handler">The REST handler.</param> /// <param name="parameter">The service method parameter.</param> /// <returns>The resource value.</returns> protected virtual object GetResourceValue(IRestServiceHandler handler, ParameterInfo parameter) { if (parameter == null) { throw new ArgumentNullException("parameter"); } if (handler == null) { throw new ArgumentNullException("handler"); } string contentType = handler.Context.Request.Headers.ContentType; if (String.IsNullOrEmpty(contentType)) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType, Resources.Global.MissingOrInvalidContentType); } IMediaTypeFormatter formatter = MediaTypeFormatterRegistry.GetHandlerFormatter(handler, contentType) ?? MediaTypeFormatterRegistry.GetFormatter(contentType); if (formatter == null || !formatter.CanFormatRequest) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType, Resources.Global.MissingOrInvalidContentType); } object argumentValue; try { argumentValue = formatter.FormatRequest(handler.Context, parameter.ParameterType); if (argumentValue != null) { LogRequest(handler.Context); } } catch (Exception ex) { if (ExceptionUnwrapper.IsDirectResponseException(ex)) { throw; } var httpException = ex as HttpException; if (httpException != null) { throw new HttpResponseException((HttpStatusCode) httpException.GetHttpCode(), httpException.Message); } throw new HttpResponseException(HttpStatusCode.BadRequest, Resources.Global.InvalidResourceBody); } return argumentValue; }
private static void ProcessRequest(IRestServiceHandler handler) { var handlerTask = Task.Factory.FromAsync(handler.BeginProcessRequest, handler.EndProcessRequest, (HttpContext) null, null); try { handlerTask.Wait(); } catch (AggregateException ex) { throw ex.InnerException; } }