public static void ThrowIf(this OperationContext context, bool condition, string faultCode, string valueName, string message, params object[] args) { if (!condition) { return; } var msg = StringHelper.SafeFormat(message, args); var fault = new ClientFault() { Code = faultCode, Tag = valueName, Message = msg }; context.ClientFaults.Add(fault); context.ClientFaults.Throw(); }
public static string ToLogString(this ClientFault fault) { try { if (fault == null) { return(null); } var result = Util.SafeFormat(" Fault: {0} Code={1} Tag ={2} Path={3}.", fault.Message, fault.Code, fault.Tag, fault.Path); if (fault.Parameters.Count > 0) { result += string.Join(";", fault.Parameters.Select(kv => Util.SafeFormat("{0}: {1}", kv.Key, kv.Value.TrimMiddle()))); } return(result); } catch (Exception ex) { //had been burned by this return("LoggingExtensions - catastrophic failure in ToLogString(): " + ex.ToString()); } }
public static ClientFault ValidateTrue(this OperationContext context, bool condition, string faultCode, string valueName, object invalidValue, string message, params object[] args) { if (condition) { return(null); } var msg = StringHelper.SafeFormat(message, args); var fault = new ClientFault() { Code = faultCode, Tag = valueName, Message = msg }; if (invalidValue != null) { fault.Parameters["InvalidValue"] = invalidValue.ToString(); } context.ClientFaults.Add(fault); return(fault); }
public static ClientFault ValidateEntity(this OperationContext context, object entity, bool condition, string faultCode, string propertyName, object invalidValue, string message, params object[] args) { if (condition) { return(null); } var rec = EntityHelper.GetRecord(entity); var recPath = rec.EntityInfo.EntityType.Name + "/" + rec.PrimaryKey.ToString(); var fault = new ClientFault() { Code = faultCode, Tag = propertyName, Message = Util.SafeFormat(message, args), Path = recPath }; if (invalidValue != null) { fault.Parameters["InvalidValue"] = invalidValue.ToString(); } rec.AddValidationFault(fault); return(fault); }
//Sequences set of records in a looped non-trivial entity group. Assigns record.SortSubIndex value after sequencing private void SequenceSubGroup(IEnumerable<EntityRecord> records) { var graph = new Graph(); foreach (var rec in records) { var ent = rec.EntityInfo; foreach (var refMember in ent.RefMembers) { var targetEnt = rec.GetValue(refMember); //If reference is not modified or not set, then nothing to do if (targetEnt == null) continue; var targetRec = EntityHelper.GetRecord(targetEnt); // we are interested only in case when both records are inserted, or both are deleted. if (targetRec.Status != rec.Status) continue; // finally, the target record's table must be in the same SCC group - i.e. have the same SccIndex if (targetRec.EntityInfo.TopologicalIndex != rec.EntityInfo.TopologicalIndex) continue; // We have potential conflict; add vertexes and link for the conflict var thisV = graph.FindOrAdd(rec); var targetV = graph.FindOrAdd(targetRec); thisV.AddLink(targetV); } }//foreach cmd //Check if any conflicts found if (graph.Vertexes.Count == 0) return; //Build SCC graph graph.BuildScc(); // Once SCC is built, we have SCC indexes in Vertexes; use them to assign Record's TopologicalIndex bool hasNonTrivialGroups = false; foreach (var v in graph.Vertexes) { var rec = (EntityRecord)v.Tag; rec.SortSubIndex = rec.Status == EntityStatus.New ? -v.SccIndex : v.SccIndex; hasNonTrivialGroups |= v.NonTrivialGroup; } //if there are non-trivial groups, it means we have circular references in the set. if (hasNonTrivialGroups) { var entList = string.Join(",", records.Select(r=> r.PrimaryKey.ToString())); var msg = StringHelper.SafeFormat("Detected circular references between entities in an update set. Cannot commit group update. Entities: [{0}].", entList); var fault = new ClientFault() {Code = ClientFaultCodes.CircularEntityReference, Message = msg}; var faultEx = new ClientFaultException(new[] { fault }); faultEx.LogAsError = true; throw faultEx; } }
public void Add(ClientFault fault) { lock(_lock) { _faults.Add(fault); } }
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext) { if(controllerContext.ControllerDescriptor.ControllerType == typeof(SlimApiGhostController)) { var httpMethod = controllerContext.Request.Method; var subRoutes = controllerContext.RouteData.GetSubRoutes(); foreach(var sr in subRoutes) { var action = FindAction(sr.Route.RouteTemplate, httpMethod); if(action != null) return action; } // Failed to match - throw BadRequest // Note: we cannot throw ClientFaultException here - Web Api will catch it and transform into InternalServerError // We have to throw HttpResponseException which Web Api will recongnize and pass it up var fmt = controllerContext.Request.GetResponseFormatter(typeof(ClientFault[])); var badRequest = new HttpResponseMessage(HttpStatusCode.BadRequest); var fault = new ClientFault(ClientFaultCodes.InvalidUrlOrMethod, "Failed to match HTTP Method and URL to controller method."); badRequest.Content = new ObjectContent<ClientFault[]>(new [] {fault}, fmt); throw new HttpResponseException(badRequest); } //if ghost controller return base.SelectAction(controllerContext); }
private async Task<HttpResponseMessage> ProcessOperationAbortException(WebCallInfo callInfo) { var request = callInfo.Request; var webContext = callInfo.WebContext; var abortExc = webContext.Exception as OperationAbortException; if(abortExc.LogAsError) { webContext.OperationContext.LogLevel = LogLevel.Details; webContext.ErrorLogId = LogError(abortExc, webContext); } HttpResponseMessage errResp; switch(abortExc.ReasonCode) { case OperationAbortReasons.ClientFault: var cfExc = (ClientFaultException) abortExc; errResp = new HttpResponseMessage(HttpStatusCode.BadRequest); var formatter = request.GetResponseFormatter(typeof(List<ClientFault>)); errResp.Content = new ObjectContent(typeof(List<ClientFault>), cfExc.Faults, formatter); return errResp; case OperationAbortReasons.ConcurrencyViolation: errResp = new HttpResponseMessage(HttpStatusCode.Conflict); return errResp; case ClientFaultCodes.AuthenticationRequired: if(Settings.Options.IsSet(WebHandlerOptions.ReturnBadRequestOnAuthenticationRequired)) { errResp = new HttpResponseMessage(HttpStatusCode.BadRequest); var fault = new ClientFault() { Code = ClientFaultCodes.AuthenticationRequired, Message = "Authentication required." }; var fmt = request.GetResponseFormatter(typeof(IList<ClientFault>)); errResp.Content = new ObjectContent(typeof(IList<ClientFault>), new [] {fault}, fmt); return errResp; } else { errResp = new HttpResponseMessage(HttpStatusCode.Unauthorized); return errResp; } case ModelStateException.ReasonBadRequestBody: //Return BadRequest, and include detailed information about the deserializer failure errResp = new HttpResponseMessage(HttpStatusCode.BadRequest); var msExc = (ModelStateException) abortExc; var errors = msExc.ModelStateErrors; var reqContent = await WebHelper.SafeReadContent(request.Content); var requestContentTrimmed = reqContent.TrimMiddle(512); var flt = new ClientFault() {Code = ClientFaultCodes.BadContent, Message = "Failure to deserialize body or parameters: " + errors }; //Serialize it as json var errFmt = request.GetResponseFormatter(typeof(IList<ClientFault>)); errResp.Content = new ObjectContent(typeof(IList<ClientFault>), new [] {flt}, errFmt); return errResp; default: // Should never happen, currently other codes are not used. errResp = new HttpResponseMessage(HttpStatusCode.BadRequest); errResp.Content = new StringContent(abortExc.ReasonCode); return errResp; }//switch }//method
public void Add(ClientFault fault) { lock (_lock) { _faults.Add(fault); } }
}//method public void AddClientFault(ClientFault fault) { _clientFaults.Add(fault); }