/// <summary> /// Populates the view model from the data received from the request. /// </summary> /// <returns></returns> public void PopulateViewModel(RedwoodRequestContext context, RedwoodView view, string serializedPostData) { var viewModelConverter = new ViewModelJsonConverter(); // get properties var data = context.ReceivedViewModelJson = JObject.Parse(serializedPostData); var viewModelToken = (JObject)data["viewModel"]; // load CSRF token context.CsrfToken = viewModelToken["$csrfToken"].Value<string>(); if (viewModelToken["$encryptedValues"] != null) { // load encrypted values var encryptedValuesString = viewModelToken["$encryptedValues"].Value<string>(); viewModelConverter.EncryptedValues = JArray.Parse(viewModelProtector.Unprotect(encryptedValuesString, context)); } else viewModelConverter.EncryptedValues = new JArray(); // get validation path context.ModelState.ValidationTargetPath = data["validationTargetPath"].Value<string>(); // populate the ViewModel var serializer = new JsonSerializer(); serializer.Converters.Add(viewModelConverter); viewModelConverter.Populate(viewModelToken, serializer, context.ViewModel); // load the control state var walker = new ViewModelJTokenControlTreeWalker(viewModelToken, view); walker.ProcessControlTree(walker.LoadControlState); }
/// <summary> /// Serializes the validation rules. /// </summary> private JObject SerializeValidationRules(ViewModelJsonConverter viewModelConverter) { var validationRules = new JObject(); foreach (var map in viewModelConverter.UsedSerializationMaps) { var rule = new JObject(); foreach (var property in map.Properties.Where(p => p.ClientValidationRules.Any())) { rule[property.Name] = JToken.FromObject(property.ClientValidationRules); } if (rule.Count > 0) validationRules[map.Type.ToString()] = rule; } return validationRules; }
/// <summary> /// Builds the view model for the client. /// </summary> public void BuildViewModel(RedwoodRequestContext context, RedwoodView view) { // serialize the ViewModel var serializer = new JsonSerializer(); var viewModelConverter = new ViewModelJsonConverter() { EncryptedValues = new JArray(), UsedSerializationMaps = new HashSet<ViewModelSerializationMap>() }; serializer.Converters.Add(viewModelConverter); var writer = new JTokenWriter(); serializer.Serialize(writer, context.ViewModel); // save the control state var walker = new ViewModelJTokenControlTreeWalker(writer.Token, view); walker.ProcessControlTree(walker.SaveControlState); // persist CSRF token writer.Token["$csrfToken"] = context.CsrfToken; // persist encrypted values if (viewModelConverter.EncryptedValues.Count > 0) writer.Token["$encryptedValues"] = viewModelProtector.Protect(viewModelConverter.EncryptedValues.ToString(Formatting.None), context); // serialize validation rules var validationRules = SerializeValidationRules(viewModelConverter); // create result object var result = new JObject(); result["viewModel"] = writer.Token; result["url"] = context.OwinContext.Request.Uri.PathAndQuery; result["virtualDirectory"] = RedwoodMiddleware.GetVirtualDirectory(context.OwinContext); if (context.IsPostBack || context.IsSpaRequest) { result["action"] = "successfulCommand"; result["resources"] = BuildResourcesJson(context, _ => true); } else { result["renderedResources"] = JArray.FromObject(context.ResourceManager.RequiredResources); } // TODO: do not send on postbacks if (validationRules.Count > 0) result["validationRules"] = validationRules; context.ViewModelJson = result; }