/// <summary> /// 构造异步的执行action /// </summary> /// <param name="serviceExec"></param> /// <param name="service"></param> /// <param name="requestContext"></param> /// <param name="dto"></param> /// <param name="responseType"></param> /// <param name="getResult"></param> /// <returns></returns> private static Task <object> ManagedAsyncServiceMethodExec( ServiceExecFn serviceExec, object service, IRequestContext requestContext, object dto, Type responseType, Func <object, object> getResult) { Stopwatch stopwatch = new Stopwatch(); var httpRequest = requestContext != null?requestContext.Get <IHttpRequest>() : null; var httpResponse = requestContext != null?requestContext.Get <IHttpResponse>() : null; string identity = null; if (EndpointHost.ServiceManager != null && EndpointHost.MetadataMap != null && httpRequest != null) { identity = EndpointHost.Config.MetadataMap[httpRequest.ServicePath].GetOperationByOpName(httpRequest.OperationName).Key; } Task serviceTask = null; try { InjectRequestContext(service, requestContext); if (EndpointHost.Config != null && EndpointHost.Config.PreExecuteServiceFilter != null) { EndpointHost.Config.PreExecuteServiceFilter(service, httpRequest, httpResponse); } //Executes the async service and returns the task stopwatch.Start(); try { serviceTask = serviceExec(requestContext, dto) as Task; } catch (Exception) { object startTimeObject; if (httpRequest.Items.TryGetValue(ServiceCatConstants.SOA2AsyncServiceStartTimeKey, out startTimeObject)) { var startTime = (DateTime)startTimeObject; } throw; } finally { } if (serviceTask == null) // null task { throw new InvalidOperationException(ServiceUtils.AsyncOperationReturnedNullTask); } if (serviceTask.Status == TaskStatus.Created) { throw new InvalidAsynchronousStateException("Service task status is invalid: TaskStatus.Created"); } } catch (Exception ex) { TaskCompletionSource <object> tcs = new TaskCompletionSource <object>(); try { if (stopwatch.IsRunning) { stopwatch.Stop(); } var response = ErrorUtils.CreateServiceErrorResponse(httpRequest, ex, responseType); if (httpResponse != null) { httpResponse.ResponseObject = response; if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ExceptionCaught = ex; httpResponse.ExecutionResult.ServiceExceptionThrown = true; httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } } tcs.TrySetResult(response); } catch (Exception ex1) { tcs.TrySetException(ex1); } return(tcs.Task); } return(serviceTask.ContinueWith(t => { try { Exception taskException = t.Exception; stopwatch.Stop(); if (taskException != null) // handler service exception { Exception ex = taskException.InnerException ?? taskException; var responseObject = ErrorUtils.CreateServiceErrorResponse(httpRequest, ex, responseType); if (httpResponse != null) { if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ExceptionCaught = ex; // Mark service execution throws exception httpResponse.ExecutionResult.ServiceExceptionThrown = true; httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } httpResponse.ResponseObject = responseObject; } return responseObject; } object response = getResult(serviceTask); // get the real response if (response == null) // null response, create service error response { var ex = new InvalidOperationException("Null response returned by service call"); var responseObject = ErrorUtils.CreateServiceErrorResponse(httpRequest, ex, responseType); if (httpResponse != null) { httpResponse.ResponseObject = responseObject; if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ExceptionCaught = ex; httpResponse.ExecutionResult.ServiceExceptionThrown = true; httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } } return responseObject; } if (EndpointHost.Config != null && EndpointHost.Config.PostExecuteServiceFilter != null) { EndpointHost.Config.PostExecuteServiceFilter(service, httpRequest, httpResponse); } IHasResponseStatus hasResponseStatus = response as IHasResponseStatus; if (hasResponseStatus != null && hasResponseStatus.ResponseStatus != null && hasResponseStatus.ResponseStatus.Ack == AckCodeType.Failure) { if (hasResponseStatus.ResponseStatus.Errors.Count > 0) { ErrorUtils.LogError("Internal handled Service Error", httpRequest, hasResponseStatus.ResponseStatus, false, "FXD300003"); } else { ErrorUtils.LogError("Internal handled Service Error. But no error data in ResponseStatus.Errors. QA please fire bug to dev and let dev fix it.", httpRequest, hasResponseStatus.ResponseStatus, true, "FXD300028"); } } if (httpResponse != null) { httpResponse.ResponseObject = response; if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } } return response; } catch (Exception ex) // catch unexpected framework exception { var responseObject = ErrorUtils.CreateFrameworkErrorResponse(httpRequest, ex, responseType); if (httpResponse != null) { httpResponse.ResponseObject = responseObject; if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ExceptionCaught = ex; // Mark framework excution throws exception httpResponse.ExecutionResult.FrameworkExceptionThrown = true; httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } } return responseObject; } finally { if (EndpointHost.AppHost != null) { //Gets disposed by AppHost or ContainerAdapter if set EndpointHost.AppHost.Release(service); } else { using (service as IDisposable) { } } } })); }
private static object ManagedServiceMethodExec( ServiceExecFn serviceExec, object service, IRequestContext requestContext, object dto, Type responseType) { InjectRequestContext(service, requestContext); Stopwatch stopwatch = new Stopwatch(); var httpRequest = requestContext != null?requestContext.Get <IHttpRequest>() : null; var httpResponse = requestContext != null?requestContext.Get <IHttpResponse>() : null; try { if (EndpointHost.Config != null && EndpointHost.Config.PreExecuteServiceFilter != null) { EndpointHost.Config.PreExecuteServiceFilter(service, httpRequest, httpResponse); } string identity = null; if (EndpointHost.ServiceManager != null && EndpointHost.MetadataMap != null && httpRequest != null) { identity = EndpointHost.Config.MetadataMap[httpRequest.ServicePath].GetOperationByOpName(httpRequest.OperationName).Key; } object response; //Executes the service and returns the result stopwatch.Start(); try { response = serviceExec(requestContext, dto); } catch (Exception) { throw; } finally { } stopwatch.Stop(); // Record service execution time if (httpResponse != null) { httpResponse.ResponseObject = response; if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } } if (response == null) // null response { throw new NullReferenceException("Null response returned by service call"); } if (EndpointHost.Config != null && EndpointHost.Config.PostExecuteServiceFilter != null) { EndpointHost.Config.PostExecuteServiceFilter(service, httpRequest, httpResponse); } IHasResponseStatus hasResponseStatus = response as IHasResponseStatus; if (hasResponseStatus != null && hasResponseStatus.ResponseStatus != null && hasResponseStatus.ResponseStatus.Ack == AckCodeType.Failure) { if (hasResponseStatus.ResponseStatus.Errors.Count > 0) { ErrorUtils.LogError("Internal handled Service Error", httpRequest, hasResponseStatus.ResponseStatus, false, "FXD300003"); } else { ErrorUtils.LogError("Internal handled Service Error. But no error data in ResponseStatus.Errors. QA please fire bug to dev and let dev fix it.", httpRequest, hasResponseStatus.ResponseStatus, true, "FXD300028"); } } return(response); } catch (Exception ex) { var errorResponse = ErrorUtils.CreateServiceErrorResponse(httpRequest, ex, responseType); if (httpResponse != null) { httpResponse.ResponseObject = errorResponse; if (httpResponse.ExecutionResult != null) { httpResponse.ExecutionResult.ExceptionCaught = ex; // Mark service excution throws exception httpResponse.ExecutionResult.ServiceExceptionThrown = true; // take service execution time into accout even the service execution throws excetpion if (stopwatch.IsRunning) { stopwatch.Stop(); } httpResponse.ExecutionResult.ServiceExecutionTime = stopwatch.ElapsedMilliseconds; } } return(errorResponse); } finally { if (EndpointHost.AppHost != null) { //Gets disposed by AppHost or ContainerAdapter if set EndpointHost.AppHost.Release(service); } else { using (service as IDisposable) { } } } }