Reduce allocations in FormContext

This commit is contained in:
Ryan Nowak 2016-02-01 12:06:29 -08:00
parent 1142c7dfc0
commit d1fdc22b9b
5 changed files with 33 additions and 20 deletions

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
} }
// Reset the FormContext // Reset the FormContext
ViewContext.FormContext = null; ViewContext.FormContext = new FormContext();
} }
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Mvc.Rendering namespace Microsoft.AspNetCore.Mvc.Rendering
@ -56,7 +57,7 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
{ {
RenderEndOfFormContent(); RenderEndOfFormContent();
_viewContext.Writer.Write("</form>"); _viewContext.Writer.Write("</form>");
_viewContext.FormContext = null; _viewContext.FormContext = new FormContext();
} }
private void RenderEndOfFormContent() private void RenderEndOfFormContent()

View File

@ -15,9 +15,6 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
/// </summary> /// </summary>
public class ViewContext : ActionContext public class ViewContext : ActionContext
{ {
// We need a default FormContext if the user uses HTML <form> instead of an MvcForm
private readonly FormContext _defaultFormContext = new FormContext();
private FormContext _formContext; private FormContext _formContext;
private DynamicViewData _viewBag; private DynamicViewData _viewBag;
@ -84,7 +81,8 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
TempData = tempData; TempData = tempData;
Writer = writer; Writer = writer;
_formContext = _defaultFormContext; FormContext = new FormContext();
ClientValidationEnabled = htmlHelperOptions.ClientValidationEnabled; ClientValidationEnabled = htmlHelperOptions.ClientValidationEnabled;
Html5DateRenderingMode = htmlHelperOptions.Html5DateRenderingMode; Html5DateRenderingMode = htmlHelperOptions.Html5DateRenderingMode;
ValidationSummaryMessageElement = htmlHelperOptions.ValidationSummaryMessageElement; ValidationSummaryMessageElement = htmlHelperOptions.ValidationSummaryMessageElement;
@ -125,7 +123,8 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
throw new ArgumentNullException(nameof(writer)); throw new ArgumentNullException(nameof(writer));
} }
_formContext = viewContext.FormContext; FormContext = viewContext.FormContext;
ClientValidationEnabled = viewContext.ClientValidationEnabled; ClientValidationEnabled = viewContext.ClientValidationEnabled;
Html5DateRenderingMode = viewContext.Html5DateRenderingMode; Html5DateRenderingMode = viewContext.Html5DateRenderingMode;
ValidationSummaryMessageElement = viewContext.ValidationSummaryMessageElement; ValidationSummaryMessageElement = viewContext.ValidationSummaryMessageElement;
@ -144,14 +143,16 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
/// </summary> /// </summary>
public virtual FormContext FormContext public virtual FormContext FormContext
{ {
get get { return _formContext; }
{
return _formContext;
}
set set
{ {
// Never return a null form context, this is important for validation purposes. if (value == null)
_formContext = value ?? _defaultFormContext; {
throw new ArgumentNullException(nameof(value));
}
_formContext = value;
} }
} }

View File

@ -801,8 +801,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
throw new ArgumentNullException(nameof(viewContext)); throw new ArgumentNullException(nameof(viewContext));
} }
var formContext = viewContext.ClientValidationEnabled ? viewContext.FormContext : null; if (viewContext.ViewData.ModelState.IsValid && (!viewContext.ClientValidationEnabled || excludePropertyErrors))
if (viewContext.ViewData.ModelState.IsValid && (formContext == null || excludePropertyErrors))
{ {
// No client side validation/updates // No client side validation/updates
return null; return null;
@ -869,7 +868,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
tagBuilder.InnerHtml.AppendHtml(wrappedMessage); tagBuilder.InnerHtml.AppendHtml(wrappedMessage);
tagBuilder.InnerHtml.AppendHtml(htmlSummary); tagBuilder.InnerHtml.AppendHtml(htmlSummary);
if (formContext != null && !excludePropertyErrors) if (viewContext.ClientValidationEnabled && !excludePropertyErrors)
{ {
// Inform the client where to replace the list of property errors after validation. // Inform the client where to replace the list of property errors after validation.
tagBuilder.MergeAttribute("data-valmsg-summary", "true"); tagBuilder.MergeAttribute("data-valmsg-summary", "true");

View File

@ -9,8 +9,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
{ {
public class FormContext public class FormContext
{ {
private readonly Dictionary<string, bool> _renderedFields = private Dictionary<string, bool> _renderedFields;
new Dictionary<string, bool>(StringComparer.Ordinal);
private Dictionary<string, object> _formData; private Dictionary<string, object> _formData;
private IList<IHtmlContent> _endOfFormContent; private IList<IHtmlContent> _endOfFormContent;
@ -52,6 +51,19 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
public bool CanRenderAtEndOfForm { get; set; } public bool CanRenderAtEndOfForm { get; set; }
private Dictionary<string, bool> RenderedFields
{
get
{
if (_renderedFields == null)
{
_renderedFields = new Dictionary<string, bool>(StringComparer.Ordinal);
}
return _renderedFields;
}
}
public bool RenderedField(string fieldName) public bool RenderedField(string fieldName)
{ {
if (fieldName == null) if (fieldName == null)
@ -60,7 +72,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
} }
bool result; bool result;
_renderedFields.TryGetValue(fieldName, out result); RenderedFields.TryGetValue(fieldName, out result);
return result; return result;
} }
@ -72,7 +84,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
throw new ArgumentNullException(nameof(fieldName)); throw new ArgumentNullException(nameof(fieldName));
} }
_renderedFields[fieldName] = value; RenderedFields[fieldName] = value;
} }
} }
} }