public IHttpActionResult Validate(DetailsSaveModel item) { if (item == null) { throw new ArgumentNullException("item"); } DetailsModelContainer model; try { model = this.ExtractModelFromRequest(item); } catch (VeyronException ex) { this.Logger.Log(LogSeverity.Error, "Validate", ex); return this.Ok(new DetailsValidateResult { Success = false, Message = ex.Message, DetailsNamespace = item.DetailsNamespace }); } if (model.Model == null) { return this.Ok(new DetailsValidateResult { Success = false, Message = "Item not found. Was it deleted while you were editing it?", DetailsNamespace = model.Namespace }); } try { var result = new DetailsValidateResult { Success = true, DetailsNamespace = model.Namespace }; var businessBase = (IBusinessBase)model.Model; if (!businessBase.IsValid) { foreach (var error in businessBase.GetAllBrokenRules()) { result.BrokenRules.Add(new BrokenRuleModel { FieldName = error.Property, Message = error.Description, Severity = error.Severity }); } } var props = model.Model.GetAllPropertiesForInstance(); foreach (var prop in props.Keys) { var isCalculated = prop.GetCustomAttributes(typeof(CalculatedAttribute), false).Any(); if (isCalculated) { var field = new FieldReadModel(props[prop], prop); result.CalculatedFields.Add(field); } var backColor = FieldReadModel.GetBackColor(props[prop], prop); if (backColor != null) { var field = new FieldBackColorModel { SystemName = prop.Name, BackColor = backColor }; result.FieldsBackColor.Add(field); } var rewriteField = new FieldReadModel(props[prop], prop); if (rewriteField.CanRead) { result.RewriteProperties.Add(rewriteField); } } return this.Ok(result); } catch (VeyronException ex) { this.Logger.Log(LogSeverity.Error, "Validate", ex); return this.Ok(new DetailsValidateResult { Success = false, Message = ex.Message, DetailsNamespace = model.Return(m => m.Namespace, string.Empty) }); } catch (Exception ex) { this.Logger.Log(LogSeverity.Error, "Validate", ex); return this.Ok(new DetailsValidateResult { Success = false, Message = "An error occured. Check log files.", DetailsNamespace = model.Return(m => m.Namespace, string.Empty) }); } }
private DetailsModelContainer ExtractModelFromRequest(DetailsSaveModel detailsModel, IEditableRoot model = null) { var result = new DetailsModelContainer(); try { result.Namespace = detailsModel.DetailsNamespace; result.ChildIndex = detailsModel.ChildIndex; if (detailsModel.Fields != null) { detailsModel.Fields.ForEach(f => result.ChangedFields.Add(f.SystemName)); } if (model == null) { if (detailsModel.ItemId == 0) { var editClass = this.DynamicTypeManager.GetEditableRootType(detailsModel.ProcessSystemName); result.Model = (IEditableRoot)MethodCaller.CallFactoryMethod(editClass, string.Format(CultureInfo.InvariantCulture, "New{0}", detailsModel.ProcessSystemName), new object[0]); } else { result.Model = this.DynamicTypeManager.GetEditableRoot<IEditableRoot>(detailsModel.ProcessSystemName, detailsModel.ItemId); } } else { result.Model = model; } if (result.Model == null) { return result; } //System.Reflection.MethodInfo dynMethod = result.Model.GetType().GetMethod("UpdateCalculatedFields", BindingFlags.NonPublic | BindingFlags.Instance); //if (dynMethod != null) // dynMethod.Invoke(result.Model, new object[] { }); if (detailsModel.Fields != null) { foreach (var field in detailsModel.Fields) { var fullName = string.Join(".", result.Model.GetFullPropertyPath(field.SystemName)); var property = result.Model.GetPropertyByFullName(fullName); var propertyModel = result.Model.GetAncestor(property); if (field.FieldType == ColumnTypes.DisplayList || field.FieldType == ColumnTypes.ReverseReference || field.FieldType == ColumnTypes.ReverseMultiReference || field.FieldType == ColumnTypes.AuditTrail || field.FieldType == ColumnTypes.Approval || field.FieldType == ColumnTypes.File) { continue; } if (field.FieldType == ColumnTypes.Image) { var imageContent = field.Value as string; if (!string.IsNullOrEmpty(imageContent)) { field.Value = Convert.FromBase64String(imageContent); } } else if (field.FieldType == ColumnTypes.Result) { if (field.Value != null) { var resultContent = JsonConvert.DeserializeObject<ResultValueModel>((string)field.Value); if (resultContent != null) { using (new BypassPropertyCheckContext()) { propertyModel.SetValueByPropertyName(field.SystemName, resultContent.Score); var currentResultListValue = (MobileObservableCollection<ChoiceInfo>)propertyModel.GetValueByPropertyName(string.Format(CultureInfo.InvariantCulture, "{0}{1}", field.SystemName, Constants.ResultListPostfix)); if (currentResultListValue != null) { foreach (var choiceInfo in currentResultListValue) { if (choiceInfo.Score == resultContent.Score) { choiceInfo.NewItemProcessId = resultContent.NewItemProcessId ?? 0; break; } } } ResultFieldHelper.SetChoiceList(propertyModel, currentResultListValue); } continue; } } using (new BypassPropertyCheckContext()) { propertyModel.SetValueByPropertyName(field.SystemName, 0.0); } continue; } else if (field.FieldType == ColumnTypes.MultiReference) { var currentMcrValue = (ICrossRefItemList)result.Model.GetValueByPropertyName(field.SystemName); if (field.Value == null) { currentMcrValue.Clear(); continue; } var mcrContent = JsonConvert.DeserializeObject<int[]>((string)field.Value); if (mcrContent == null || mcrContent.Length == 0) { if (currentMcrValue != null) { currentMcrValue.Clear(); } continue; } var newItemsList = mcrContent.Where(mcrItem => !currentMcrValue.Contains(mcrItem)).Select(id => (ICrossRefItemInfo)this.DynamicTypeManager.GetMultiCrossReferenceItem(propertyModel.ProcessName, field.SystemName, id)).ToList(); var deletedItems = (from ICrossRefItemInfo item in currentMcrValue where !mcrContent.Contains(item.Id) select item).ToList(); currentMcrValue.RemoveRange(deletedItems); currentMcrValue.AddRange(newItemsList); continue; } else if (field.FieldType == ColumnTypes.Checklist) { var json = (string)field.Value; var items = JsonConvert.DeserializeObject<DetailsSaveModel[]>(json); var currentChecklistValue = (ChecklistEdit)result.Model.GetValueByPropertyName(field.SystemName); // extract models for each details item in checklist var answers = new List<DetailsModelContainer>(); foreach (var item in items) { // we have to check, if this is new item (item we are extracting) and it has corresponding child element in current (unmodified, loaded from db) checklist value // we should pass it as model. // if we do not do this, we will loose some fields values (fields, filled by Mapping setup in Checklist for just saved checklist process, for example). IEditableRoot childModel = null; if (item.ItemId == 0) { if (item.ChildIndex < currentChecklistValue.AnswerProcessList.Count && ((IEditableRoot)currentChecklistValue.AnswerProcessList[item.ChildIndex]).Id == 0) { childModel = (IEditableRoot)currentChecklistValue.AnswerProcessList[item.ChildIndex]; } } else { childModel = currentChecklistValue.AnswerProcessList.Cast<IEditableRoot>().FirstOrDefault(i => i.Id == item.ItemId); } answers.Add(this.ExtractModelFromRequest(item, childModel)); } if (answers.IsNullOrEmpty()) { continue; } var newItemsList = answers.Where(item => item.Model.Id != 0 && currentChecklistValue.AnswerProcessList.Cast<IEditableRoot>().All(i => i.Id != item.Model.Id)).ToList(); var deletedItemsList = (from IDynamicObject item in currentChecklistValue.AnswerProcessList where item.Id != 0 && !answers.Exists(i => i.Model.Id == item.Id) select item).ToList(); var changedItemsList = answers.Where(item => item.Model.Id != 0 && currentChecklistValue.AnswerProcessList.Cast<IEditableRoot>().Any(i => i.Id == item.Model.Id)).ToList(); for (int i = 0; i < answers.Count; i++) { try { var answer = answers[i]; if (answer.Model.Id != 0) { continue; } if (currentChecklistValue.AnswerProcessList.Count < answer.ChildIndex || ((IEditableRoot)currentChecklistValue.AnswerProcessList[answer.ChildIndex]).Id != 0) { newItemsList.Add(answer); } else { var oldItem = (IEditableRoot)currentChecklistValue.AnswerProcessList[answer.ChildIndex]; if (ReferenceEquals(oldItem, answer.Model)) { continue; } var properties = oldItem.GetAllPropertiesForInstance(); foreach (var oldAnswerProperty in properties.Where(p => answer.ChangedFields.Contains(p.Key.Name))) { if (oldAnswerProperty.Key.CanWrite && oldAnswerProperty.Value.CanWriteProperty(oldAnswerProperty.Key.Name)) { using (new BypassPropertyCheckContext()) { oldAnswerProperty.Value.SetValueByPropertyName(oldAnswerProperty.Key.Name, (object)answer.Model.GetValueByPropertyName(oldAnswerProperty.Key.Name)); } } } } } catch (Exception ex) { Logger.Log(LogSeverity.Error, "ProcessController", ex); Debugger.Break(); } } foreach (var answer in deletedItemsList) { currentChecklistValue.AnswerProcessList.Remove(answer); } foreach (var answer in newItemsList) { answer.Model.MakeChild(); currentChecklistValue.AnswerProcessList.Add(answer.Model); } foreach (var answer in changedItemsList) { IEditableRoot answer1 = answer.Model; var oldAnswer = (IEditableRoot)currentChecklistValue.AnswerProcessList.FindFirst(i => i, v => v.Id == answer1.Id); if (ReferenceEquals(oldAnswer, answer.Model)) { continue; } var properties = oldAnswer.GetAllPropertiesForInstance(); foreach (var oldAnswerProperty in properties.Where(p => answer.ChangedFields.Contains(p.Key.Name) || p.Key.GetCustomAttributes(typeof(FieldEditorAttribute), false).Cast<FieldEditorAttribute>().Any(f => f.DataType == Constants.ChoiceFieldType))) { if (oldAnswerProperty.Key.CanWrite && oldAnswerProperty.Value.CanWriteProperty(oldAnswerProperty.Key.Name)) { using (new BypassPropertyCheckContext()) { try { oldAnswerProperty.Value.SetValueByPropertyName(oldAnswerProperty.Key.Name, (object)answer.Model.GetValueByPropertyName(oldAnswerProperty.Key.Name)); } catch (Exception ex) { Debug.WriteLine(ex.Message); Debugger.Break(); } } } } } continue; } else if (field.FieldType == ColumnTypes.Sample) { var currentSampleValue = (ISampleList)result.Model.GetValueByPropertyName(field.SystemName); var sampleContent = JsonConvert.DeserializeObject<SampleModel[]>((string)field.Value); if (sampleContent == null || sampleContent.Length == 0) { currentSampleValue.Clear(); continue; } var samples = new List<ISampleEdit>(); foreach (var item in sampleContent) { ISampleEdit childModel = null; if (item.Id == 0) { if (item.ChildIndex < currentSampleValue.Count && ((ISampleEdit)currentSampleValue[item.ChildIndex]).Id == 0) { childModel = (ISampleEdit)currentSampleValue[item.ChildIndex]; } else { currentSampleValue.AddSample(result.Model.Id); childModel = (ISampleEdit)currentSampleValue[currentSampleValue.Count - 1]; } } else { childModel = currentSampleValue.Cast<ISampleEdit>().FirstOrDefault(i => i.Id == item.Id); } ExtractSample(item, childModel); samples.Add(childModel); } if (samples.IsNullOrEmpty()) { continue; } var deletedItemsList = (from IDynamicObject item in currentSampleValue where item.Id != 0 && sampleContent.All(i => i.Id != item.Id) select item).ToList(); foreach (var answer in deletedItemsList) { currentSampleValue.Remove(answer); } continue; } else if (field.FieldType == ColumnTypes.SampleType) { if (field.Value != null) { var sampleTypeContent = JsonConvert.DeserializeObject<SampleTypeValueModel>((string)field.Value); if (sampleTypeContent != null) { using (new BypassPropertyCheckContext()) { propertyModel.SetValueByPropertyName(field.SystemName, sampleTypeContent.SampleType); propertyModel.SetValueByPropertyName(field.SystemName + Constants.SampleTrueLabel, sampleTypeContent.TrueLabel); propertyModel.SetValueByPropertyName(field.SystemName + Constants.SampleFalseLabel, sampleTypeContent.FalseLabel); } continue; } } using (new BypassPropertyCheckContext()) { propertyModel.SetValueByPropertyName(field.SystemName, SampleTypes.Number.ToString()); } continue; } using (new BypassPropertyCheckContext()) // workaround { try { propertyModel.SetValueByPropertyName(field.SystemName, SafeTypeConverter.Convert(field.Value, result.Model.GetPropertyByName(field.SystemName).PropertyType)); } catch (Exception ex) { Debug.WriteLine(ex.Message); Debugger.Break(); } } } } if (detailsModel.NextStateGuid != null) { var supportStates = result.Model as ISupportStates; if (supportStates != null && (supportStates.CurrentStateGuid != detailsModel.NextStateGuid.Value)) { var nextState = supportStates.GetNextAvailableStates().FirstOrDefault(s => s.Guid == detailsModel.NextStateGuid.Value); if (nextState != null) { supportStates.CurrentState = nextState.Id; } else { throw new VeyronException("Selected next state is not available for current item state. Was item modified while you were editing it?"); } } } UpdateModelDefaultValues(result.Model); } catch (Exception ex) { Debug.WriteLine(ex.Message); throw; } return result; }
public IHttpActionResult Save(DetailsSaveModel item) { if (item == null) { throw new ArgumentNullException("item"); } DetailsModelContainer model; try { model = this.ExtractModelFromRequest(item); } catch (VeyronException ex) { this.Logger.Log(LogSeverity.Error, "Save", ex); return this.Ok(new DetailsSaveResult { Success = false, Message = ex.Message, DetailsNamespace = item.DetailsNamespace }); } if (model.Model == null) { return this.Ok(new DetailsSaveResult { Success = false, Message = "Item not found. Was it deleted while you were editing it?", DetailsNamespace = model.Namespace }); } var businessBase = (IBusinessBase)model.Model; if (!businessBase.IsValid) { var result = new DetailsSaveResult { Success = false, Message = businessBase.Error, DetailsNamespace = model.Namespace }; foreach (var error in businessBase.GetAllBrokenRules()) { result.BrokenRules.Add(new BrokenRuleModel { FieldName = error.Property, Message = error.Description, Severity = error.Severity }); } return this.Ok(result); } IEditableRoot newModel; try { newModel = (IEditableRoot)businessBase.Save(); } catch (DataPortalException ex) { var indexViolation = ex.BusinessException as UniqueIndexViolationException; if (indexViolation != null) { var message = new StringBuilder(); var uniqueIndexError = JsonConvert.DeserializeObject<MobileList<UniqueIndexViolationError>>(indexViolation.Message, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }); foreach (var uniqueIndexViolationError in uniqueIndexError) { message.AppendLine(); message.AppendFormat( CultureInfo.InvariantCulture, LanguageService.Translate("Error_UniqueDataIndexViolation"), uniqueIndexViolationError.IndexName, string.Join(",", uniqueIndexViolationError.IndexFields.Select(x => model.Model.GetPropertyDisplayName(x) ?? x)), uniqueIndexViolationError.ViolationMessage); } return this.Ok(new DetailsSaveResult { Success = false, Message = message.ToString(), DetailsNamespace = model.Namespace }); } return this.Ok(new DetailsSaveResult { Success = false, Message = ex.ToString(), DetailsNamespace = model.Namespace }); } catch (Exception ex) { return this.Ok(new DetailsSaveResult { Success = false, Message = ex.ToString(), DetailsNamespace = model.Namespace }); } try { return this.Ok(new DetailsSaveResult { Success = true, ItemId = newModel.Id, DetailsNamespace = model.Namespace, Model = CreateDetailsReadModel(newModel) }); } catch (Exception ex) { return this.Ok(new DetailsSaveResult { Success = false, Message = ex.ToString(), DetailsNamespace = model.Namespace }); } }