/// <summary> /// Executes a view asynchronously. /// </summary> /// <param name="actionContext">The <see cref="ActionContext"/> associated with the current request.</param> /// <param name="view">The <see cref="IView"/>.</param> /// <param name="viewData">The <see cref="ViewDataDictionary"/>.</param> /// <param name="tempData">The <see cref="ITempDataDictionary"/>.</param> /// <param name="contentType"> /// The content-type header value to set in the response. If <c>null</c>, /// <see cref="DefaultContentType"/> will be used. /// </param> /// <param name="statusCode"> /// The HTTP status code to set in the response. May be <c>null</c>. /// </param> /// <returns>A <see cref="Task"/> which will complete when view execution is completed.</returns> public virtual async Task ExecuteAsync( ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, int?statusCode) { if (actionContext == null) { throw new ArgumentNullException(nameof(actionContext)); } if (view == null) { throw new ArgumentNullException(nameof(view)); } if (ViewOptions == null) { throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull(nameof(ViewOptions), GetType().Name)); } if (TempDataFactory == null) { throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull(nameof(TempDataFactory), GetType().Name)); } if (ModelMetadataProvider == null) { throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull(nameof(ModelMetadataProvider), GetType().Name)); } if (viewData == null) { viewData = new ViewDataDictionary(ModelMetadataProvider, actionContext.ModelState); } if (tempData == null) { tempData = TempDataFactory.GetTempData(actionContext.HttpContext); } var viewContext = new ViewContext( actionContext, view, viewData, tempData, TextWriter.Null, ViewOptions.HtmlHelperOptions); await ExecuteAsync(viewContext, contentType, statusCode); }
/// <summary> /// Executes a view asynchronously. /// </summary> /// <param name="actionContext">The <see cref="ActionContext"/> associated with the current request.</param> /// <param name="view">The <see cref="IView"/>.</param> /// <param name="viewData">The <see cref="ViewDataDictionary"/>.</param> /// <param name="tempData">The <see cref="ITempDataDictionary"/>.</param> /// <param name="contentType"> /// The content-type header value to set in the response. If <c>null</c>, /// <see cref="DefaultContentType"/> will be used. /// </param> /// <param name="statusCode"> /// The HTTP status code to set in the response. May be <c>null</c>. /// </param> /// <returns>A <see cref="Task"/> which will complete when view execution is completed.</returns> public virtual async Task ExecuteAsync( ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, int?statusCode) { if (actionContext == null) { throw new ArgumentNullException(nameof(actionContext)); } if (view == null) { throw new ArgumentNullException(nameof(view)); } if (viewData == null) { viewData = new ViewDataDictionary(_modelMetadataProvider, actionContext.ModelState); } if (tempData == null) { tempData = TempDataFactory.GetTempData(actionContext.HttpContext); } var response = actionContext.HttpContext.Response; string resolvedContentType = null; Encoding resolvedContentTypeEncoding = null; ResponseContentTypeHelper.ResolveContentTypeAndEncoding( contentType, response.ContentType, DefaultContentType, out resolvedContentType, out resolvedContentTypeEncoding); response.ContentType = resolvedContentType; if (statusCode != null) { response.StatusCode = statusCode.Value; } using (var writer = WriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding)) { var viewContext = new ViewContext( actionContext, view, viewData, tempData, writer, ViewOptions.HtmlHelperOptions); DiagnosticSource.BeforeView(view, viewContext); await view.RenderAsync(viewContext); DiagnosticSource.AfterView(view, viewContext); // Perf: Invoke FlushAsync to ensure any buffered content is asynchronously written to the underlying // response asynchronously. In the absence of this line, the buffer gets synchronously written to the // response as part of the Dispose which has a perf impact. await writer.FlushAsync(); } }