diff --git a/src/ServiceStack.Interfaces/ServiceHost/IServiceController.cs b/src/ServiceStack.Interfaces/ServiceHost/IServiceController.cs
index f5c189cfcc7..0a1dcba239e 100644
--- a/src/ServiceStack.Interfaces/ServiceHost/IServiceController.cs
+++ b/src/ServiceStack.Interfaces/ServiceHost/IServiceController.cs
@@ -1,45 +1,50 @@
-using System;
-using System.Collections.Generic;
-
-namespace ServiceStack.ServiceHost
-{
- ///
- /// Responsible for executing the operation within the specified context.
- ///
- /// The operation types.
- public interface IServiceController
- {
- ///
- /// Returns a list of operation types available in this service
- ///
- /// The operation types.
- IList OperationTypes { get; }
-
- ///
- /// Returns a list of ALL operation types available in this service
- ///
- /// The operation types.
- IList AllOperationTypes { get; }
-
- ///
- /// Returns the first matching RestPath
- ///
- ///
- ///
- ///
- IRestPath GetRestPathForRequest(string httpMethod, string pathInfo);
-
- ///
- /// Allow the registration of custom routes
- ///
- IServiceRoutes Routes { get; }
-
- ///
- /// Executes the DTO request under the supplied requestContext.
- ///
- ///
- ///
- ///
- object Execute(object request, IRequestContext requestContext);
- }
+using System;
+using System.Collections.Generic;
+
+namespace ServiceStack.ServiceHost
+{
+ ///
+ /// Responsible for executing the operation within the specified context.
+ ///
+ /// The operation types.
+ public interface IServiceController
+ {
+ ///
+ /// Returns a list of operation types available in this service
+ ///
+ /// The operation types.
+ IList OperationTypes { get; }
+
+ ///
+ /// Returns a list of ALL operation types available in this service
+ ///
+ /// The operation types.
+ IList AllOperationTypes { get; }
+
+ ///
+ /// Returns the first matching RestPath
+ ///
+ ///
+ ///
+ ///
+ IRestPath GetRestPathForRequest(string httpMethod, string pathInfo);
+
+ ///
+ /// Allow the registration of custom routes
+ ///
+ IServiceRoutes Routes { get; }
+
+ ///
+ /// Executes the DTO request with no requestContext.
+ ///
+ object Execute(object dto);
+
+ ///
+ /// Executes the DTO request under the supplied requestContext.
+ ///
+ ///
+ ///
+ ///
+ object Execute(object request, IRequestContext requestContext);
+ }
}
\ No newline at end of file
diff --git a/src/ServiceStack/ServiceHost/NServiceExec.cs b/src/ServiceStack/ServiceHost/NServiceExec.cs
index a5194b8f41d..13e3fd486ab 100644
--- a/src/ServiceStack/ServiceHost/NServiceExec.cs
+++ b/src/ServiceStack/ServiceHost/NServiceExec.cs
@@ -1,165 +1,167 @@
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using System.Reflection;
-using ServiceStack.ServiceClient.Web;
-using ServiceStack.Text;
-using ServiceStack.WebHost.Endpoints;
-
-namespace ServiceStack.ServiceHost
-{
- public interface INServiceExec
- {
- object Execute(IRequestContext requestContext, object instance, object request);
- }
-
- public class NServiceRequestExec : INServiceExec
- {
- static NServiceRequestExec()
- {
- NServiceExec.CreateServiceRunnersFor();
- }
-
- public object Execute(IRequestContext requestContext, object instance, object request)
- {
- return NServiceExec.Execute(requestContext, instance, request,
- typeof(TRequest).Name);
- }
- }
-
- public class NServiceExec
- {
- private static Dictionary> actionMap
- = new Dictionary>();
-
- private static Dictionary execMap
- = new Dictionary();
-
- static NServiceExec()
- {
- var mis = typeof(TService).GetMethods(BindingFlags.Public | BindingFlags.Instance);
- foreach (var methodInfo in mis)
- {
- var mi = methodInfo;
- if (mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void)) continue;
- var args = mi.GetParameters();
- if (args.Length != 1) continue;
- var actionName = mi.Name.ToUpper();
- if (!HttpMethod.AllVerbs.Contains(actionName) && actionName != ActionContext.AnyAction)
- continue;
-
- var requestType = args[0].ParameterType;
- var actionCtx = new ActionContext {
- Id = ActionContext.Key(actionName, requestType.Name),
- RequestType = requestType,
- };
-
- try
- {
- actionCtx.ServiceAction = CreateExecFn(requestType, mi);
- }
- catch
- {
- //Potential problems with MONO, using reflection for fallback
- actionCtx.ServiceAction = (service, request) =>
- mi.Invoke(service, new[] { request });
- }
-
- var reqFilters = new List();
- var resFilters = new List();
-
- foreach (var attr in mi.GetCustomAttributes(false))
- {
- var hasReqFilter = attr as IHasRequestFilter;
- var hasResFilter = attr as IHasResponseFilter;
-
- if (hasReqFilter != null)
- reqFilters.Add(hasReqFilter);
-
- if (hasResFilter != null)
- resFilters.Add(hasResFilter);
- }
-
- if (reqFilters.Count > 0)
- actionCtx.RequestFilters = reqFilters.ToArray();
-
- if (resFilters.Count > 0)
- actionCtx.ResponseFilters = resFilters.ToArray();
-
- if (!actionMap.ContainsKey(requestType))
- actionMap[requestType] = new List();
-
- actionMap[requestType].Add(actionCtx);
- }
- }
-
- public static ActionInvokerFn CreateExecFn(Type requestType, MethodInfo mi)
- {
- var serviceType = typeof(TService);
-
- var serviceParam = Expression.Parameter(typeof(object), "serviceObj");
- var serviceStrong = Expression.Convert(serviceParam, serviceType);
-
- var requestDtoParam = Expression.Parameter(typeof(object), "requestDto");
- var requestDtoStrong = Expression.Convert(requestDtoParam, requestType);
-
- Expression callExecute = Expression.Call(
- serviceStrong, mi, requestDtoStrong);
-
- if (mi.ReturnType != typeof(void))
- {
- var executeFunc = Expression.Lambda
- (callExecute, serviceParam, requestDtoParam).Compile();
-
- return executeFunc;
- }
- else
- {
- var executeFunc = Expression.Lambda
- (callExecute, serviceParam, requestDtoParam).Compile();
-
- return (service, request) => {
- executeFunc(service, request);
- return null;
- };
- }
- }
-
- public static List GetActionsFor()
- {
- List requestActions;
- return actionMap.TryGetValue(typeof(TRequest), out requestActions)
- ? requestActions
- : new List();
- }
-
- public static void CreateServiceRunnersFor()
- {
- foreach (var actionCtx in GetActionsFor())
- {
- if (execMap.ContainsKey(actionCtx.Id)) continue;
-
- var serviceRunner = EndpointHost.CreateServiceRunner(actionCtx);
- execMap[actionCtx.Id] = serviceRunner.Process;
- }
- }
-
- public static object Execute(IRequestContext requestContext,
- object instance, object request, string requestName)
- {
- var actionName = requestContext.Get().HttpMethod;
-
- InstanceExecFn action;
- if (execMap.TryGetValue(ActionContext.Key(actionName, requestName), out action)
- || execMap.TryGetValue(ActionContext.AnyKey(requestName), out action))
- {
- return action(requestContext, instance, request);
- }
-
- var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLower();
- throw new NotImplementedException(
- "Could not find method named {1}({0}) or Any({0}) on Service {2}"
- .Fmt(request.GetType().Name, expectedMethodName, typeof(TService).Name));
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+using ServiceStack.ServiceClient.Web;
+using ServiceStack.Text;
+using ServiceStack.WebHost.Endpoints;
+
+namespace ServiceStack.ServiceHost
+{
+ public interface INServiceExec
+ {
+ object Execute(IRequestContext requestContext, object instance, object request);
+ }
+
+ public class NServiceRequestExec : INServiceExec
+ {
+ static NServiceRequestExec()
+ {
+ NServiceExec.CreateServiceRunnersFor();
+ }
+
+ public object Execute(IRequestContext requestContext, object instance, object request)
+ {
+ return NServiceExec.Execute(requestContext, instance, request,
+ typeof(TRequest).Name);
+ }
+ }
+
+ public class NServiceExec
+ {
+ private static Dictionary> actionMap
+ = new Dictionary>();
+
+ private static Dictionary execMap
+ = new Dictionary();
+
+ static NServiceExec()
+ {
+ var mis = typeof(TService).GetMethods(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var methodInfo in mis)
+ {
+ var mi = methodInfo;
+ if (mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void)) continue;
+ var args = mi.GetParameters();
+ if (args.Length != 1) continue;
+ var actionName = mi.Name.ToUpper();
+ if (!HttpMethod.AllVerbs.Contains(actionName) && actionName != ActionContext.AnyAction)
+ continue;
+
+ var requestType = args[0].ParameterType;
+ var actionCtx = new ActionContext {
+ Id = ActionContext.Key(actionName, requestType.Name),
+ RequestType = requestType,
+ };
+
+ try
+ {
+ actionCtx.ServiceAction = CreateExecFn(requestType, mi);
+ }
+ catch
+ {
+ //Potential problems with MONO, using reflection for fallback
+ actionCtx.ServiceAction = (service, request) =>
+ mi.Invoke(service, new[] { request });
+ }
+
+ var reqFilters = new List();
+ var resFilters = new List();
+
+ foreach (var attr in mi.GetCustomAttributes(false))
+ {
+ var hasReqFilter = attr as IHasRequestFilter;
+ var hasResFilter = attr as IHasResponseFilter;
+
+ if (hasReqFilter != null)
+ reqFilters.Add(hasReqFilter);
+
+ if (hasResFilter != null)
+ resFilters.Add(hasResFilter);
+ }
+
+ if (reqFilters.Count > 0)
+ actionCtx.RequestFilters = reqFilters.ToArray();
+
+ if (resFilters.Count > 0)
+ actionCtx.ResponseFilters = resFilters.ToArray();
+
+ if (!actionMap.ContainsKey(requestType))
+ actionMap[requestType] = new List();
+
+ actionMap[requestType].Add(actionCtx);
+ }
+ }
+
+ public static ActionInvokerFn CreateExecFn(Type requestType, MethodInfo mi)
+ {
+ var serviceType = typeof(TService);
+
+ var serviceParam = Expression.Parameter(typeof(object), "serviceObj");
+ var serviceStrong = Expression.Convert(serviceParam, serviceType);
+
+ var requestDtoParam = Expression.Parameter(typeof(object), "requestDto");
+ var requestDtoStrong = Expression.Convert(requestDtoParam, requestType);
+
+ Expression callExecute = Expression.Call(
+ serviceStrong, mi, requestDtoStrong);
+
+ if (mi.ReturnType != typeof(void))
+ {
+ var executeFunc = Expression.Lambda
+ (callExecute, serviceParam, requestDtoParam).Compile();
+
+ return executeFunc;
+ }
+ else
+ {
+ var executeFunc = Expression.Lambda
+ (callExecute, serviceParam, requestDtoParam).Compile();
+
+ return (service, request) => {
+ executeFunc(service, request);
+ return null;
+ };
+ }
+ }
+
+ public static List GetActionsFor()
+ {
+ List requestActions;
+ return actionMap.TryGetValue(typeof(TRequest), out requestActions)
+ ? requestActions
+ : new List();
+ }
+
+ public static void CreateServiceRunnersFor()
+ {
+ foreach (var actionCtx in GetActionsFor())
+ {
+ if (execMap.ContainsKey(actionCtx.Id)) continue;
+
+ var serviceRunner = EndpointHost.CreateServiceRunner(actionCtx);
+ execMap[actionCtx.Id] = serviceRunner.Process;
+ }
+ }
+
+ public static object Execute(IRequestContext requestContext,
+ object instance, object request, string requestName)
+ {
+ var actionName = requestContext != null
+ ? requestContext.Get().HttpMethod
+ : HttpMethod.Post; //MQ Services
+
+ InstanceExecFn action;
+ if (execMap.TryGetValue(ActionContext.Key(actionName, requestName), out action)
+ || execMap.TryGetValue(ActionContext.AnyKey(requestName), out action))
+ {
+ return action(requestContext, instance, request);
+ }
+
+ var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLower();
+ throw new NotImplementedException(
+ "Could not find method named {1}({0}) or Any({0}) on Service {2}"
+ .Fmt(request.GetType().Name, expectedMethodName, typeof(TService).Name));
+ }
+ }
}
\ No newline at end of file
diff --git a/src/ServiceStack/ServiceHost/ServiceRunner.cs b/src/ServiceStack/ServiceHost/ServiceRunner.cs
index 641a83d1a55..2da1b7a321f 100644
--- a/src/ServiceStack/ServiceHost/ServiceRunner.cs
+++ b/src/ServiceStack/ServiceHost/ServiceRunner.cs
@@ -1,188 +1,188 @@
-using System;
-using System.Diagnostics;
-using ServiceStack.Common;
-using ServiceStack.Common.Web;
-using ServiceStack.Logging;
-using ServiceStack.Messaging;
-using ServiceStack.ServiceClient.Web;
-using ServiceStack.Text;
-using ServiceStack.WebHost.Endpoints;
-
-namespace ServiceStack.ServiceHost
-{
- public class ServiceRunner : IServiceRunner
- {
- protected static readonly ILog Log = LogManager.GetLogger(typeof(ServiceRunner<>));
-
- protected readonly IAppHost AppHost;
- protected readonly ActionInvokerFn ServiceAction;
- protected readonly IHasRequestFilter[] RequestFilters;
- protected readonly IHasResponseFilter[] ResponseFilters;
-
- public ServiceRunner() { }
-
- public ServiceRunner(IAppHost appHost, ActionContext actionContext)
- {
- this.AppHost = appHost;
- this.ServiceAction = actionContext.ServiceAction;
- this.RequestFilters = actionContext.RequestFilters;
- this.ResponseFilters = actionContext.ResponseFilters;
- }
-
- public IAppHost GetAppHost()
- {
- return AppHost ?? EndpointHost.AppHost;
- }
-
- public T TryResolve()
- {
- return this.GetAppHost() == null
- ? default(T)
- : this.GetAppHost().TryResolve();
- }
-
- public T ResolveService(IRequestContext requestContext)
- {
- var service = this.GetAppHost().TryResolve();
- var requiresContext = service as IRequiresRequestContext;
- if (requiresContext != null)
- {
- requiresContext.RequestContext = requestContext;
- }
- return service;
- }
-
- public virtual void BeforeEachRequest(IRequestContext requestContext, TRequest request)
- {
- OnBeforeExecute(requestContext, request);
-
- var requestLogger = TryResolve();
- if (requestLogger != null)
- {
- requestContext.SetItem("_requestDurationStopwatch", Stopwatch.StartNew());
- }
- }
-
- public virtual object AfterEachRequest(IRequestContext requestContext, TRequest request, object response)
- {
- var requestLogger = TryResolve();
- if (requestLogger != null)
- {
- try
- {
- var stopWatch = (Stopwatch)requestContext.GetItem("_requestDurationStopwatch");
- requestLogger.Log(requestContext, request, response, stopWatch.Elapsed);
- }
- catch (Exception ex)
- {
- Log.Error("Error while logging request: " + request.Dump(), ex);
- }
- }
-
- //only call OnAfterExecute if no exception occured
- return response.IsErrorResponse() ? response : OnAfterExecute(requestContext, response);
- }
-
- public virtual void OnBeforeExecute(IRequestContext requestContext, TRequest request) { }
-
- public virtual object OnAfterExecute(IRequestContext requestContext, object response)
- {
- return response;
- }
-
- public virtual object Execute(IRequestContext requestContext, object instance, TRequest request)
- {
- try
- {
- BeforeEachRequest(requestContext, request);
-
- var httpReq = requestContext.Get();
- var httpRes = requestContext.Get();
-
- if (RequestFilters != null)
- {
- foreach (var requestFilter in RequestFilters)
- {
- requestFilter.RequestFilter(httpReq, httpRes, request);
- if (httpRes.IsClosed) return null;
- }
- }
-
- var response = AfterEachRequest(requestContext, request, ServiceAction(instance, request));
-
- if (ResponseFilters != null)
- {
- foreach (var responseFilter in ResponseFilters)
- {
- responseFilter.ResponseFilter(httpReq, httpRes, response);
- if (httpRes.IsClosed) return null;
- }
- }
-
- return response;
- }
- catch (Exception ex)
- {
- var result = HandleException(requestContext, request, ex);
-
- if (result == null) throw;
-
- return result;
- }
- }
-
- public virtual object Execute(IRequestContext requestContext, object instance, IMessage request)
- {
- return Execute(requestContext, instance, request.GetBody());
- }
-
- public virtual object HandleException(IRequestContext requestContext, TRequest request, Exception ex)
- {
- var useAppHost = GetAppHost();
-
- //TODO workout validation errors
- var errorResponse = useAppHost != null && useAppHost.ServiceExceptionHandler != null
- ? useAppHost.ServiceExceptionHandler(request, ex)
- : DtoUtils.HandleException(useAppHost, request, ex);
-
- AfterEachRequest(requestContext, request, errorResponse ?? ex);
-
- return errorResponse;
- }
-
- public object ExecuteOneWay(IRequestContext requestContext, object instance, TRequest request)
- {
- var msgFactory = TryResolve();
- if (msgFactory == null)
- {
- return Execute(requestContext, instance, request);
- }
-
- //Capture and persist this async request on this Services 'In Queue'
- //for execution after this request has been completed
- using (var producer = msgFactory.CreateMessageProducer())
- {
- producer.Publish(request);
- }
-
- return WebRequestUtils.GetErrorResponseDtoType(request).CreateInstance();
- }
-
- //signature matches ServiceExecFn
- public object Process(IRequestContext requestContext, object instance, object request)
- {
- return Execute(requestContext, instance, (TRequest)request);
- }
-
- public object ProcessOneWay(IRequestContext requestContext, object instance, object request)
- {
- return ExecuteOneWay(requestContext, instance, (TRequest)request);
- }
-
- public object Process(IRequestContext requestContext, object instance, IMessage message)
- {
- return Execute(requestContext, instance, (IMessage)message);
- }
- }
-
+using System;
+using System.Diagnostics;
+using ServiceStack.Common;
+using ServiceStack.Common.Web;
+using ServiceStack.Logging;
+using ServiceStack.Messaging;
+using ServiceStack.ServiceClient.Web;
+using ServiceStack.Text;
+using ServiceStack.WebHost.Endpoints;
+
+namespace ServiceStack.ServiceHost
+{
+ public class ServiceRunner : IServiceRunner
+ {
+ protected static readonly ILog Log = LogManager.GetLogger(typeof(ServiceRunner<>));
+
+ protected readonly IAppHost AppHost;
+ protected readonly ActionInvokerFn ServiceAction;
+ protected readonly IHasRequestFilter[] RequestFilters;
+ protected readonly IHasResponseFilter[] ResponseFilters;
+
+ public ServiceRunner() { }
+
+ public ServiceRunner(IAppHost appHost, ActionContext actionContext)
+ {
+ this.AppHost = appHost;
+ this.ServiceAction = actionContext.ServiceAction;
+ this.RequestFilters = actionContext.RequestFilters;
+ this.ResponseFilters = actionContext.ResponseFilters;
+ }
+
+ public IAppHost GetAppHost()
+ {
+ return AppHost ?? EndpointHost.AppHost;
+ }
+
+ public T TryResolve()
+ {
+ return this.GetAppHost() == null
+ ? default(T)
+ : this.GetAppHost().TryResolve();
+ }
+
+ public T ResolveService(IRequestContext requestContext)
+ {
+ var service = this.GetAppHost().TryResolve();
+ var requiresContext = service as IRequiresRequestContext;
+ if (requiresContext != null)
+ {
+ requiresContext.RequestContext = requestContext;
+ }
+ return service;
+ }
+
+ public virtual void BeforeEachRequest(IRequestContext requestContext, TRequest request)
+ {
+ OnBeforeExecute(requestContext, request);
+
+ var requestLogger = TryResolve();
+ if (requestLogger != null)
+ {
+ requestContext.SetItem("_requestDurationStopwatch", Stopwatch.StartNew());
+ }
+ }
+
+ public virtual object AfterEachRequest(IRequestContext requestContext, TRequest request, object response)
+ {
+ var requestLogger = TryResolve();
+ if (requestLogger != null)
+ {
+ try
+ {
+ var stopWatch = (Stopwatch)requestContext.GetItem("_requestDurationStopwatch");
+ requestLogger.Log(requestContext, request, response, stopWatch.Elapsed);
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Error while logging request: " + request.Dump(), ex);
+ }
+ }
+
+ //only call OnAfterExecute if no exception occured
+ return response.IsErrorResponse() ? response : OnAfterExecute(requestContext, response);
+ }
+
+ public virtual void OnBeforeExecute(IRequestContext requestContext, TRequest request) { }
+
+ public virtual object OnAfterExecute(IRequestContext requestContext, object response)
+ {
+ return response;
+ }
+
+ public virtual object Execute(IRequestContext requestContext, object instance, TRequest request)
+ {
+ try
+ {
+ BeforeEachRequest(requestContext, request);
+
+ var httpReq = requestContext != null ? requestContext.Get() : null;
+ var httpRes = requestContext != null ? requestContext.Get() : null;
+
+ if (RequestFilters != null)
+ {
+ foreach (var requestFilter in RequestFilters)
+ {
+ requestFilter.RequestFilter(httpReq, httpRes, request);
+ if (httpRes != null && httpRes.IsClosed) return null;
+ }
+ }
+
+ var response = AfterEachRequest(requestContext, request, ServiceAction(instance, request));
+
+ if (ResponseFilters != null)
+ {
+ foreach (var responseFilter in ResponseFilters)
+ {
+ responseFilter.ResponseFilter(httpReq, httpRes, response);
+ if (httpRes != null && httpRes.IsClosed) return null;
+ }
+ }
+
+ return response;
+ }
+ catch (Exception ex)
+ {
+ var result = HandleException(requestContext, request, ex);
+
+ if (result == null) throw;
+
+ return result;
+ }
+ }
+
+ public virtual object Execute(IRequestContext requestContext, object instance, IMessage request)
+ {
+ return Execute(requestContext, instance, request.GetBody());
+ }
+
+ public virtual object HandleException(IRequestContext requestContext, TRequest request, Exception ex)
+ {
+ var useAppHost = GetAppHost();
+
+ //TODO workout validation errors
+ var errorResponse = useAppHost != null && useAppHost.ServiceExceptionHandler != null
+ ? useAppHost.ServiceExceptionHandler(request, ex)
+ : DtoUtils.HandleException(useAppHost, request, ex);
+
+ AfterEachRequest(requestContext, request, errorResponse ?? ex);
+
+ return errorResponse;
+ }
+
+ public object ExecuteOneWay(IRequestContext requestContext, object instance, TRequest request)
+ {
+ var msgFactory = TryResolve();
+ if (msgFactory == null)
+ {
+ return Execute(requestContext, instance, request);
+ }
+
+ //Capture and persist this async request on this Services 'In Queue'
+ //for execution after this request has been completed
+ using (var producer = msgFactory.CreateMessageProducer())
+ {
+ producer.Publish(request);
+ }
+
+ return WebRequestUtils.GetErrorResponseDtoType(request).CreateInstance();
+ }
+
+ //signature matches ServiceExecFn
+ public object Process(IRequestContext requestContext, object instance, object request)
+ {
+ return Execute(requestContext, instance, (TRequest)request);
+ }
+
+ public object ProcessOneWay(IRequestContext requestContext, object instance, object request)
+ {
+ return ExecuteOneWay(requestContext, instance, (TRequest)request);
+ }
+
+ public object Process(IRequestContext requestContext, object instance, IMessage message)
+ {
+ return Execute(requestContext, instance, (IMessage)message);
+ }
+ }
+
}
\ No newline at end of file