示例#1
0
        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();
        }
示例#2
0
 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());
     }
 }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
 //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;
       }
 }
示例#6
0
 public void Add(ClientFault fault)
 {
     lock(_lock) {
     _faults.Add(fault);
       }
 }
示例#7
0
 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);
 }
示例#8
0
    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
示例#9
0
 public void Add(ClientFault fault)
 {
     lock (_lock) {
         _faults.Add(fault);
     }
 }
示例#10
0
        }//method

        public void AddClientFault(ClientFault fault)
        {
            _clientFaults.Add(fault);
        }