private void Render(InitializeTagHelperStructure source, CSharpRenderingContext context) { // Call into the tag helper scope manager to start a new tag helper scope. // Also capture the value as the current execution context. context.Writer .WriteStartAssignment(ExecutionContextVariableName) .WriteStartInstanceMethodInvocation( ScopeManagerVariableName, context.CodeLiterals.GeneratedTagHelperContext.ScopeManagerBeginMethodName); // Assign a unique ID for this instance of the source HTML tag. This must be unique // per call site, e.g. if the tag is on the view twice, there should be two IDs. context.Writer.WriteStringLiteral(source.TagName) .WriteParameterSeparator() .Write("global::") .Write(typeof(TagMode).FullName) .Write(".") .Write(source.TagMode.ToString()) .WriteParameterSeparator() .WriteStringLiteral(GenerateUniqueTagHelperId()) .WriteParameterSeparator(); // We remove and redirect writers so TagHelper authors can retrieve content. var nonRedirectedConventions = new CSharpRenderingConventions(context); using (context.UseRenderingConventions(nonRedirectedConventions)) using (context.Writer.BuildAsyncLambda(endLine: false)) { context.Render(source.Children); } context.Writer.WriteEndMethodInvocation(); }
public static CSharpRenderingConventions GetRenderingConventions(this CSharpRenderingContext context) { var conventions = context.Items[typeof(CSharpRenderingConventions)] as CSharpRenderingConventions; if (conventions == null) { conventions = new CSharpRenderingConventions(context); SetRenderingConventions(context, conventions); } return(conventions); }
public static IDisposable UseRenderingConventions( this CSharpRenderingContext context, CSharpRenderingConventions conventions) { var initialConventions = context.GetRenderingConventions(); var scope = new ActionScope(() => { context.SetRenderingConventions(initialConventions); }); context.SetRenderingConventions(conventions); return(scope); }
private static void SetRenderingConventions( this CSharpRenderingContext context, CSharpRenderingConventions conventions) { context.Items[typeof(CSharpRenderingConventions)] = conventions; }
private static void Render(AddTagHelperHtmlAttribute source, CSharpRenderingContext context) { var attributeValueStyleParameter = $"global::{typeof(HtmlAttributeValueStyle).FullName}.{source.ValueStyle}"; var isConditionalAttributeValue = source.ValuePieces.Any(child => child is ConditionalAttributePiece); // All simple text and minimized attributes will be pre-allocated. if (isConditionalAttributeValue) { // Dynamic attribute value should be run through the conditional attribute removal system. It's // unbound and contains C#. // TagHelper attribute rendering is buffered by default. We do not want to write to the current // writer. var valuePieceCount = source.ValuePieces.Count(piece => piece is LiteralAttributePiece || piece is ConditionalAttributePiece); context.Writer .WriteStartMethodInvocation(context.CodeLiterals.GeneratedTagHelperContext.BeginAddHtmlAttributeValuesMethodName) .Write(ExecutionContextVariableName) .WriteParameterSeparator() .WriteStringLiteral(source.Name) .WriteParameterSeparator() .Write(valuePieceCount.ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator() .Write(attributeValueStyleParameter) .WriteEndMethodInvocation(); var renderingConventions = new TagHelperHtmlAttributeRenderingConventions(context); using (context.UseRenderingConventions(renderingConventions)) { context.Render(source.ValuePieces); } context.Writer .WriteMethodInvocation( context.CodeLiterals.GeneratedTagHelperContext.EndAddHtmlAttributeValuesMethodName, ExecutionContextVariableName); } else { // This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or // other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to // determine its final value. // Attribute value is not plain text, must be buffered to determine its final value. context.Writer.WriteMethodInvocation(context.CodeLiterals.GeneratedTagHelperContext.BeginWriteTagHelperAttributeMethodName); // We're building a writing scope around the provided chunks which captures everything written from the // page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to // ensure we capture all content that's written, directly or indirectly. var nonRedirectedConventions = new CSharpRenderingConventions(context); using (context.UseRenderingConventions(nonRedirectedConventions)) { context.Render(source.ValuePieces); } context.Writer .WriteStartAssignment(StringValueBufferVariableName) .WriteMethodInvocation(context.CodeLiterals.GeneratedTagHelperContext.EndWriteTagHelperAttributeMethodName) .WriteStartInstanceMethodInvocation( ExecutionContextVariableName, context.CodeLiterals.GeneratedTagHelperContext.ExecutionContextAddHtmlAttributeMethodName) .WriteStringLiteral(source.Name) .WriteParameterSeparator() .WriteStartMethodInvocation(context.CodeLiterals.GeneratedTagHelperContext.MarkAsHtmlEncodedMethodName) .Write(StringValueBufferVariableName) .WriteEndMethodInvocation(endLine: false) .WriteParameterSeparator() .Write(attributeValueStyleParameter) .WriteEndMethodInvocation(); } }