private static RuleExecutionResponseType ParseResponseType(RuleExecutionResponse response) { // take response type string and convert it to enum var responseTypeEnum = (RuleExecutionResponseType)0; if (String.IsNullOrEmpty(response.ResponseType)) { responseTypeEnum = RuleExecutionResponseType.NotSpecified; response.ResponseType = RuleExecutionResponseType.NotSpecified.ToString(); } else { var responseTypesList = response.ResponseType.Split(Delimeter.ToCharArray()).ToList(); foreach (var responseType in responseTypesList) { if (!Enum.IsDefined(typeof(RuleExecutionResponseType), responseType)) { throw new Exception("The requested response type is not a valid option. Invalid response type: " + responseType); } responseTypeEnum |= (RuleExecutionResponseType)Enum.Parse(typeof(RuleExecutionResponseType), responseType); } } return(responseTypeEnum); }
public static void HandleWebException(Exception ex, RuleExecutionResponse response) { try { LogException(ex); } catch (Exception logEx) { // do not let logging failures affect the ability to return a response response.Error += String.Format("\r\n\r\nError logging failed on server: {0}", logEx.Message); } if (WebOperationContext.Current.IncomingRequest.Method == "POST") { var debug = OperationContext.Current.Host.Description.Behaviors.Find <ServiceDebugBehavior>(); var includeStackTrace = (debug != null && debug.IncludeExceptionDetailInFaults); response.Error = includeStackTrace ? ex.ToString() : ex.Message; //WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError; //WebOperationContext.Current.OutgoingResponse.StatusDescription = WebUtility.HtmlEncode(ex.Message.Replace("\n", " ").Replace("\r", " ")); WebOperationContext.Current.OutgoingResponse.ContentType = ResponseContentType; } else { // rethrow on GET verb throw ex; } }
private static void ProcessResponseTypes(bool isPost, RuleExecutionResponse response, RuleExecutionResponseType responseTypeEnum, out bool useResponseContainer, out string contentType) { var responseTypeCount = (response.ResponseType == null) ? 0 : response.ResponseType.Split(Delimeter.ToCharArray()).Length; var usingXml = false; var usingReport = false; useResponseContainer = false; // if it is a post, we always return the RuleExecutionResponse if (isPost) { contentType = ResponseContentType; useResponseContainer = true; return; } if ( responseTypeEnum.HasFlag(RuleExecutionResponseType.NotificationsXml) || responseTypeEnum.HasFlag(RuleExecutionResponseType.EntityXml) || responseTypeEnum.HasFlag(RuleExecutionResponseType.ValidationsXml) || responseTypeEnum.HasFlag(RuleExecutionResponseType.RuleExecutionResponseXml) || responseTypeEnum.HasFlag(RuleExecutionResponseType.NotSpecified) ) { usingXml = true; } if ( responseTypeEnum.HasFlag(RuleExecutionResponseType.NotificationsText) || responseTypeEnum.HasFlag(RuleExecutionResponseType.PerformanceStatisticsReport) || responseTypeEnum.HasFlag(RuleExecutionResponseType.RuleExecutionReport) || responseTypeEnum.HasFlag(RuleExecutionResponseType.ValidationsText) ) { usingReport = true; } // special case for allowing notification and validation text if (responseTypeEnum.HasFlag(RuleExecutionResponseType.NotificationsText) && responseTypeEnum.HasFlag(RuleExecutionResponseType.ValidationsText) && responseTypeCount == 2) { contentType = ResponseContentType; return; } if ((usingXml && usingReport) || (usingReport && responseTypeCount > 1)) { throw new Exception("The requested response types are not a valid combination. Invalid response types: " + response.ResponseType.Replace(Delimeter, ", ")); } contentType = usingReport ? "text/html" : ResponseContentType; if (responseTypeCount > 1 || responseTypeEnum.HasFlag(RuleExecutionResponseType.RuleExecutionResponseXml) || responseTypeEnum.HasFlag(RuleExecutionResponseType.NotSpecified)) { useResponseContainer = true; } }
public static void SetResponseValidations(RuleSession session, RuleExecutionResponse response) { if (session.GetValidations().Count > 0) { response.Validations = new List <Validation>(); foreach (var val in session.GetValidations()) { var validation = new Validation { Message = val.Target + " - " + val.Message }; response.Validations.Add(validation); } } }
public static void SetResponseNotifications(RuleSession session, RuleExecutionResponse response) { if (session.GetNotifications().Count > 0) { response.Notifications = new List <Notification>(); foreach (var note in session.GetNotifications()) { var notification = new Notification { Message = note.Message, Type = note.Type.ToString() }; response.Notifications.Add(notification); } } }
public static void SetResponseText(RuleSession session, Entity entity, RuleExecutionResponse response) { response.ResponseText = ""; var isPost = WebOperationContext.Current.IncomingRequest.Method == "POST"; // force local cache expiration for future requests WebOperationContext.Current.OutgoingResponse.Headers.Add(HttpResponseHeader.Expires, DateTime.Now.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss 'GMT'")); WebOperationContext.Current.OutgoingResponse.Headers.Add(HttpResponseHeader.CacheControl, "no-cache"); var responseTypeEnum = ParseResponseType(response); // validate response types and set content type bool useResponseContainer; string contentType; ProcessResponseTypes(isPost, response, responseTypeEnum, out useResponseContainer, out contentType); if (responseTypeEnum.HasFlag(RuleExecutionResponseType.EntityXml)) { if (entity != null) { var xml = GetEntityXml(entity); if (useResponseContainer || isPost) { response.EntityXml = xml; } else { response.ResponseText = xml; } } else { response.ResponseText = "Warning: Entity is null or not found"; } } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.NotificationsXml)) { SetResponseNotifications(session, response); if (!useResponseContainer) { response.ResponseText = Serialize(response.Notifications, "Notifications"); } } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.ValidationsXml)) { SetResponseValidations(session, response); if (!useResponseContainer) { response.ResponseText = Serialize(response.Validations, "Validations"); } } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.ExecutionLogXml)) { var xml = GetExecutionLogXml(session.LastRuleExecutionLog); if (useResponseContainer || isPost) { response.ExecutionLogXml = xml; } else { response.ResponseText = xml; } } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.NotificationsText)) { response.ResponseText += GetNotificationText(session); } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.ValidationsText)) { response.ResponseText += GetValidationText(session); } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.ExecutionLogText)) { response.ResponseText = GetExecutionLogText(session); } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.RuleExecutionResponseXml) || responseTypeEnum.HasFlag(RuleExecutionResponseType.NotSpecified)) { // always uses container response.EntityXml = GetEntityXml(entity); response.ExecutionLogXml = GetExecutionLogXml(session.LastRuleExecutionLog); SetResponseNotifications(session, response); SetResponseValidations(session, response); } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.RuleExecutionReport)) { response.ResponseText = GetRuleExecutionReport(session, entity); } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.PerformanceStatisticsReport)) { response.ResponseText = GetPerformanceStatisticsReport(session); } if (responseTypeEnum.HasFlag(RuleExecutionResponseType.Invalid)) { response.ResponseText = "Warning: Invalid ResponseType Specified"; contentType = ResponseContentType; } if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.ContentType = contentType; } if (useResponseContainer && !isPost) { response.ResponseText = Serialize(response); } }
/// <summary> /// Method used when performing a POST request and by public GET methods to centralize all rule execution. /// Auto, explicit and independent rules can be executed in the method, based on the type of request specified. /// </summary> /// <param name="request">A RuleExecutionRequest that contains all execution information required to run rules.</param> /// <returns>RuleExecutionResponse</returns> public RuleExecutionResponse ExecuteRuleRequest(RuleExecutionRequest request) { var response = new RuleExecutionResponse(); try { // get rule application using settings from web.config var ruleApp = GetRuleApp(request.RuleApp); using (var session = new RuleSession(ruleApp)) { // override end points RuleServiceHelper.OverrideEndPoints(session, request); // if the performance stats report was requested, turn on the details if (request.ResponseType != null && request.ResponseType.Contains(RuleExecutionResponseType.PerformanceStatisticsReport.ToString())) { session.Settings.LogOptions = EngineLogOptions.SummaryStatistics | EngineLogOptions.DetailStatistics; } // if the execution report or execution log was requested, turn on the execution and state change settings if (request.ResponseType != null && (request.ResponseType.Contains(RuleExecutionResponseType.RuleExecutionReport.ToString()) || request.ResponseType.Contains(RuleExecutionResponseType.ExecutionLogText.ToString()) || request.ResponseType.Contains(RuleExecutionResponseType.ExecutionLogXml.ToString()))) { session.Settings.LogOptions = EngineLogOptions.Execution | EngineLogOptions.StateChanges; } response.ResponseType = request.ResponseType; Entity entity = null; if (!String.IsNullOrEmpty(request.Entity)) { // if an entity was specified, this is an entity based rule set entity = session.CreateEntity(request.Entity); // if state was passed in, load it if (!String.IsNullOrEmpty(request.EntityXml)) { entity.ParseXml(request.EntityXml); } // if an explicit rule set was not specified, call ApplyRules if (String.IsNullOrEmpty(request.RuleSet)) { session.ApplyRules(); } else { // this is an explicit rule set, if parameters were passed in, pass them to the explicit rule set if (request.Parameters.Count > 0) { var parameters = BuildRuleSetParameters(request, session); entity.ExecuteRuleSet(request.RuleSet, parameters.ToArray()); } else { entity.ExecuteRuleSet(request.RuleSet); } } } else { // if no entity name was passed in, this is an independent rule set, pass parameters if applicable if (request.Parameters.Count > 0) { var parameters = BuildRuleSetParameters(request, session); session.ExecuteIndependentRuleSet(request.RuleSet, parameters.ToArray()); } else { session.ExecuteIndependentRuleSet(request.RuleSet); } } // if output entity was specified, Entity returnEntity; if (string.IsNullOrEmpty(request.ReturnEntity)) { returnEntity = entity; } else { // retrieve output entity returnEntity = RuleServiceHelper.GetEntityFromRuleSession(session, request.ReturnEntity); } // set the response text based on the request type RuleServiceHelper.SetResponseText(session, returnEntity, response); } } catch (Exception ex) { RuleServiceHelper.HandleWebException(ex, response); } return(response); }