private async Task <ModelBindingResult> RunModelBinders(ModelBindingContext bindingContext) { RuntimeHelpers.EnsureSufficientExecutionStack(); // Perf: Avoid allocations for (var i = 0; i < ModelBinders.Count; i++) { var binder = ModelBinders[i]; var result = await binder.BindModelAsync(bindingContext); if (result != ModelBindingResult.NoResult) { // This condition is necessary because the ModelState entry would never be validated if // caller fell back to the empty prefix, leading to an possibly-incorrect !IsValid. In most // (hopefully all) cases, the ModelState entry exists because some binders add errors before // returning a result with !IsModelSet. Those binders often cannot run twice anyhow. if (result.IsModelSet || bindingContext.ModelState.ContainsKey(bindingContext.ModelName)) { if (bindingContext.IsTopLevelObject && result.Model != null) { ValidationStateEntry entry; if (!bindingContext.ValidationState.TryGetValue(result.Model, out entry)) { entry = new ValidationStateEntry(); bindingContext.ValidationState.Add(result.Model, entry); } entry.Key = entry.Key ?? result.Key; entry.Metadata = entry.Metadata ?? bindingContext.ModelMetadata; } return(result); } // Current binder should have been able to bind value but found nothing. Exit loop in a way that // tells caller to fall back to the empty prefix, if appropriate. Do not return result because it // means only "other binders are not applicable". break; } } // Either we couldn't find a binder, or the binder couldn't bind. Distinction is not important. return(ModelBindingResult.NoResult); }
private async Task RunModelBinders(ModelBindingContext bindingContext) { RuntimeHelpers.EnsureSufficientExecutionStack(); ModelBindingResult?overallResult = null; try { using (bindingContext.EnterNestedScope()) { if (PrepareBindingContext(bindingContext)) { // Perf: Avoid allocations for (var i = 0; i < ModelBinders.Count; i++) { var binder = ModelBinders[i]; await binder.BindModelAsync(bindingContext); if (bindingContext.Result != null) { var result = bindingContext.Result.Value; // This condition is necessary because the ModelState entry would never be validated if // caller fell back to the empty prefix, leading to an possibly-incorrect !IsValid. In most // (hopefully all) cases, the ModelState entry exists because some binders add errors before // returning a result with !IsModelSet. Those binders often cannot run twice anyhow. if (result.IsModelSet || bindingContext.ModelState.ContainsKey(bindingContext.ModelName)) { if (bindingContext.IsTopLevelObject && result.Model != null) { ValidationStateEntry entry; if (!bindingContext.ValidationState.TryGetValue(result.Model, out entry)) { entry = new ValidationStateEntry() { Key = result.Key, Metadata = bindingContext.ModelMetadata, }; bindingContext.ValidationState.Add(result.Model, entry); } } overallResult = bindingContext.Result; return; } // Current binder should have been able to bind value but found nothing. Exit loop in a way that // tells caller to fall back to the empty prefix, if appropriate. Do not return result because it // means only "other binders are not applicable". // overallResult MUST still be null at this return statement. return; } } } } } finally { bindingContext.Result = overallResult; } }