/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Shared/RazorViews/BaseView.cs
288 строк
9 KB
Martin Costello
Use char overloads (#56531)
19 июл 2024, 19:45
Не верифицирован
19 июл 2024, 19:45
dfc5189
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Http; #nullable enable #pragma warning disable IDE0060 // Unused members are required by codegen. namespace Microsoft.Extensions.RazorViews; /// <summary> /// Infrastructure /// </summary> internal abstract class BaseView { private static readonly Encoding UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); private static readonly char[] NewLineChars = new[] { '\r', '\n' }; private readonly Stack<TextWriter> _textWriterStack = new Stack<TextWriter>(); /// <summary> /// The request context /// </summary> protected HttpContext Context { get; private set; } = default!; /// <summary> /// The request /// </summary> protected HttpRequest Request { get; private set; } = default!; /// <summary> /// The response /// </summary> protected HttpResponse Response { get; private set; } = default!; /// <summary> /// The output stream /// </summary> protected TextWriter Output { get; private set; } = default!; /// <summary> /// Html encoder used to encode content. /// </summary> protected HtmlEncoder HtmlEncoder { get; set; } = HtmlEncoder.Default; /// <summary> /// Url encoder used to encode content. /// </summary> protected UrlEncoder UrlEncoder { get; set; } = UrlEncoder.Default; /// <summary> /// JavaScript encoder used to encode content. /// </summary> protected JavaScriptEncoder JavaScriptEncoder { get; set; } = JavaScriptEncoder.Default; /// <summary> /// Execute an individual request /// </summary> /// <param name="stream">The stream to write to</param> public async Task ExecuteAsync(Stream stream) { // We technically don't need this intermediate buffer if this method accepts a memory stream. var buffer = new MemoryStream(); Output = new StreamWriter(buffer, UTF8NoBOM, 4096, leaveOpen: true); await ExecuteAsync(); await Output.FlushAsync(); await Output.DisposeAsync(); buffer.Seek(0, SeekOrigin.Begin); await buffer.CopyToAsync(stream); } /// <summary> /// Execute an individual request /// </summary> /// <param name="context"></param> public async Task ExecuteAsync(HttpContext context) { Context = context; Request = Context.Request; Response = Context.Response; var buffer = new MemoryStream(); Output = new StreamWriter(buffer, UTF8NoBOM, 4096, leaveOpen: true); await ExecuteAsync(); await Output.FlushAsync(); await Output.DisposeAsync(); buffer.Seek(0, SeekOrigin.Begin); await buffer.CopyToAsync(Response.Body); } /// <summary> /// Execute an individual request /// </summary> public abstract Task ExecuteAsync(); protected virtual void PushWriter(TextWriter writer) { ArgumentNullException.ThrowIfNull(writer); _textWriterStack.Push(Output); Output = writer; } protected virtual TextWriter PopWriter() { Output = _textWriterStack.Pop(); return Output; } /// <summary> /// Write the given value without HTML encoding directly to <see cref="Output"/>. /// </summary> /// <param name="value">The <see cref="object"/> to write.</param> protected void WriteLiteral(object value) { WriteLiteral(Convert.ToString(value, CultureInfo.InvariantCulture)); } /// <summary> /// Write the given value without HTML encoding directly to <see cref="Output"/>. /// </summary> /// <param name="value">The <see cref="string"/> to write.</param> protected void WriteLiteral(string? value) { if (!string.IsNullOrEmpty(value)) { Output.Write(value); } } private List<string>? AttributeValues { get; set; } protected void WriteAttributeValue(string thingy, int startPostion, object value, int endValue, int dealyo, bool yesno) { if (AttributeValues == null) { AttributeValues = new List<string>(); } AttributeValues.Add(value.ToString()!); } private string? AttributeEnding { get; set; } protected void BeginWriteAttribute(string name, string beginning, int startPosition, string ending, int endPosition, int thingy) { Debug.Assert(string.IsNullOrEmpty(AttributeEnding)); Output.Write(beginning); AttributeEnding = ending; } protected void EndWriteAttribute() { Debug.Assert(AttributeValues != null); Debug.Assert(!string.IsNullOrEmpty(AttributeEnding)); var attributes = string.Join(' ', AttributeValues); Output.Write(attributes); AttributeValues = null; Output.Write(AttributeEnding); AttributeEnding = null; } /// <summary> /// Writes the given attribute to the given writer /// </summary> /// <param name="name">The name of the attribute to write</param> /// <param name="leader">The value of the prefix</param> /// <param name="trailer">The value of the suffix</param> /// <param name="values">The <see cref="AttributeValue"/>s to write.</param> protected void WriteAttribute( string name, string leader, string trailer, params AttributeValue[] values) { ArgumentNullException.ThrowIfNull(name); ArgumentNullException.ThrowIfNull(leader); ArgumentNullException.ThrowIfNull(trailer); WriteLiteral(leader); foreach (var value in values) { WriteLiteral(value.Prefix); // The special cases here are that the value we're writing might already be a string, or that the // value might be a bool. If the value is the bool 'true' we want to write the attribute name // instead of the string 'true'. If the value is the bool 'false' we don't want to write anything. // Otherwise the value is another object (perhaps an HtmlString) and we'll ask it to format itself. string? stringValue; if (value.Value is bool flag) { if (flag) { stringValue = name; } else { continue; } } else { stringValue = value.Value as string; } // Call the WriteTo(string) overload when possible if (value.Literal && stringValue != null) { WriteLiteral(stringValue); } else if (value.Literal) { WriteLiteral(value.Value); } else if (stringValue != null) { Write(stringValue); } else { Write(value.Value); } } WriteLiteral(trailer); } /// <summary> /// <see cref="HelperResult.WriteTo(TextWriter)"/> is invoked /// </summary> /// <param name="result">The <see cref="HelperResult"/> to invoke</param> protected void Write(HelperResult result) { result.WriteTo(Output); } /// <summary> /// Writes the specified <paramref name="value"/> to <see cref="Output"/>. /// </summary> /// <param name="value">The <see cref="object"/> to write.</param> /// <remarks> /// <see cref="HelperResult.WriteTo(TextWriter)"/> is invoked for <see cref="HelperResult"/> types. /// For all other types, the encoded result of <see cref="object.ToString"/> is written to /// <see cref="Output"/>. /// </remarks> protected void Write(object value) { if (value is HelperResult helperResult) { helperResult.WriteTo(Output); } else { Write(Convert.ToString(value, CultureInfo.InvariantCulture)); } } /// <summary> /// Writes the specified <paramref name="value"/> with HTML encoding to <see cref="Output"/>. /// </summary> /// <param name="value">The <see cref="string"/> to write.</param> protected void Write(string? value) { if (!string.IsNullOrEmpty(value)) { WriteLiteral(HtmlEncoder.Encode(value)); } } protected string HtmlEncodeAndReplaceLineBreaks(string input) { if (string.IsNullOrEmpty(input)) { return string.Empty; } // Split on line breaks before passing it through the encoder. return string.Join("<br />" + Environment.NewLine, input.Split("\r\n", StringSplitOptions.None) .SelectMany(s => s.Split(NewLineChars, StringSplitOptions.None)) .Select(HtmlEncoder.Encode)); } }