Пример #1
0
        public string RenderToStringAsync(string viewName, object model)
        {
            var httpContext = new DefaultHttpContext {
                RequestServices = _serviceProvider
            };
            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            using (var sw = new StringWriter())
            {
                var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);

                if (viewResult.View == null)
                {
                    throw new ArgumentNullException($"{viewName} does not match any available view");
                }

                var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
                {
                    Model = model
                };

                var viewContext = new ViewContext(
                    actionContext,
                    viewResult.View,
                    viewDictionary,
                    new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
                    sw,
                    new HtmlHelperOptions()
                    );

                viewResult.View.RenderAsync(viewContext);
                return(sw.ToString());
            }
        }
Пример #2
0
        public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult result)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            var response = context.HttpContext.Response;

            var viewData = result.ViewData;

            if (viewData == null)
            {
                viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
            }

            var tempData = result.TempData;

            if (tempData == null)
            {
                tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext);
            }

            ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
                result.ContentType,
                response.ContentType,
                (ViewExecutor.DefaultContentType, Encoding.UTF8),
                MediaType.GetEncoding,
                out var resolvedContentType,
                out var resolvedContentTypeEncoding);

            response.ContentType = resolvedContentType;

            if (result.StatusCode != null)
            {
                response.StatusCode = result.StatusCode.Value;
            }

            await using var writer = _writerFactory.CreateWriter(response.Body, resolvedContentTypeEncoding);
            var viewContext = new ViewContext(
                context,
                NullView.Instance,
                viewData,
                tempData,
                writer,
                _htmlHelperOptions);

            OnExecuting(viewContext);

            // IViewComponentHelper is stateful, we want to make sure to retrieve it every time we need it.
            var viewComponentHelper = context.HttpContext.RequestServices.GetRequiredService <IViewComponentHelper>();

            (viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);
            var viewComponentResult = await GetViewComponentResult(viewComponentHelper, _logger, result);

            if (viewComponentResult is ViewBuffer viewBuffer)
            {
                // In the ordinary case, DefaultViewComponentHelper will return an instance of ViewBuffer. We can simply
                // invoke WriteToAsync on it.
                await viewBuffer.WriteToAsync(writer, _htmlEncoder);

                await writer.FlushAsync();
            }
            else
            {
                await using var bufferingStream = new FileBufferingWriteStream();
                await using (var intermediateWriter = _writerFactory.CreateWriter(bufferingStream, resolvedContentTypeEncoding))
                {
                    viewComponentResult.WriteTo(intermediateWriter, _htmlEncoder);
                }

                await bufferingStream.DrainBufferAsync(response.Body);
            }
        }
Пример #3
0
 public ViewDataDictionary(ViewDataDictionary source, object?model)
     : base(source, model, declaredModelType: typeof(TModel))
 {
 }
Пример #4
0
 public ViewDataDictionary(ViewDataDictionary source)
     : base(source, declaredModelType: typeof(TModel))
 {
 }
Пример #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ViewDataDictionary"/> class based entirely on an existing
 /// instance.
 /// </summary>
 /// <param name="source"><see cref="ViewDataDictionary"/> instance to copy initial values from.</param>
 /// <remarks>
 /// <para>
 /// For use when copying a <see cref="ViewDataDictionary"/> instance and the declared <see cref="Model"/>
 /// <see cref="Type"/> will not change e.g. when copying from a <see cref="ViewDataDictionary{TModel}"/>
 /// instance to a base <see cref="ViewDataDictionary"/> instance.
 /// </para>
 /// <para>
 /// This constructor should not be used in any context where <see cref="Model"/> may be set to a value
 /// incompatible with the declared type of <paramref name="source"/>.
 /// </para>
 /// </remarks>
 public ViewDataDictionary(ViewDataDictionary source)
     : this(source, source.Model, source._declaredModelType)
 {
 }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ViewDataDictionary"/> class based in part on an existing
        /// instance. This constructor is careful to avoid exceptions <see cref="SetModel"/> may throw when
        /// <paramref name="model"/> is <c>null</c>.
        /// </summary>
        /// <param name="source"><see cref="ViewDataDictionary"/> instance to copy initial values from.</param>
        /// <param name="model">Value for the <see cref="Model"/> property.</param>
        /// <param name="declaredModelType">
        /// <see cref="Type"/> of <see cref="Model"/> values expected. Used to set <see cref="ModelMetadata"/>.
        /// </param>
        /// <remarks>
        /// <para>
        /// For use when copying a <see cref="ViewDataDictionary"/> instance and new instance's declared
        /// <see cref="Model"/> <see cref="Type"/> and <see cref="Model"/> are known.
        /// </para>
        /// <para>
        /// This constructor may <c>throw</c> if <paramref name="model"/> is non-<c>null</c> and incompatible with
        /// <paramref name="declaredModelType"/>.
        /// </para>
        /// </remarks>
        // This is the core constructor called when Model is known.
        protected ViewDataDictionary(ViewDataDictionary source, object model, Type declaredModelType)
            : this(source._metadataProvider,
                   source.ModelState,
                   declaredModelType,
                   data : new CopyOnWriteDictionary <string, object>(source, StringComparer.OrdinalIgnoreCase),
                   templateInfo : new TemplateInfo(source.TemplateInfo))
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            // A non-null Model must always be assignable to both _declaredModelType and ModelMetadata.ModelType.
            //
            // ModelMetadata.ModelType should also be assignable to _declaredModelType. Though corner cases exist such
            // as a ViewDataDictionary<List<int>> holding information about an IEnumerable<int> property (because an
            // @model directive matched the runtime type though the view's name did not), we'll throw away the property
            // metadata in those cases -- preserving invariant that ModelType can be assigned to _declaredModelType.
            //
            // More generally, since defensive copies to base VDD and VDD<object> abound, it's important to preserve
            // metadata despite _declaredModelType changes.
            var modelType           = model?.GetType();
            var modelOrDeclaredType = modelType ?? declaredModelType;

            if (source.ModelMetadata.MetadataKind == ModelMetadataKind.Type &&
                source.ModelMetadata.ModelType == typeof(object) &&
                modelOrDeclaredType != typeof(object))
            {
                // Base ModelMetadata on new type when there's no property information to preserve and type changes to
                // something besides typeof(object).
                ModelExplorer = _metadataProvider.GetModelExplorerForType(modelOrDeclaredType, model);
            }
            else if (!declaredModelType.IsAssignableFrom(source.ModelMetadata.ModelType))
            {
                // Base ModelMetadata on new type when existing metadata is incompatible with the new declared type.
                ModelExplorer = _metadataProvider.GetModelExplorerForType(modelOrDeclaredType, model);
            }
            else if (modelType != null && !source.ModelMetadata.ModelType.IsAssignableFrom(modelType))
            {
                // Base ModelMetadata on new type when new model is incompatible with the existing metadata.
                ModelExplorer = _metadataProvider.GetModelExplorerForType(modelType, model);
            }
            else if (object.ReferenceEquals(model, source.ModelExplorer.Model))
            {
                // Source's ModelExplorer is already exactly correct.
                ModelExplorer = source.ModelExplorer;
            }
            else
            {
                // The existing metadata is compatible with the value and declared type but it's a new value.
                ModelExplorer = new ModelExplorer(
                    _metadataProvider,
                    source.ModelExplorer.Container,
                    source.ModelMetadata,
                    model);
            }

            // Ensure the given Model is compatible with _declaredModelType. Do not do this one of the following
            // special cases:
            // - Constructing a ViewDataDictionary<TModel> where TModel is a non-Nullable value type. This may for
            // example occur when activating a RazorPage<int> and the container is null.
            // - Constructing a ViewDataDictionary<object> immediately before overwriting ModelExplorer with correct
            // information. See TemplateBuilder.Build().
            if (model != null)
            {
                EnsureCompatible(model);
            }
        }
Пример #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ViewDataDictionary"/> class based in part on an existing
 /// instance.
 /// </summary>
 /// <param name="source"><see cref="ViewDataDictionary"/> instance to copy initial values from.</param>
 /// <param name="declaredModelType">
 /// <see cref="Type"/> of <see cref="Model"/> values expected. Used to set <see cref="ModelMetadata"/>.
 /// </param>
 /// <remarks>
 /// <para>
 /// For use when copying a <see cref="ViewDataDictionary"/> instance and new instance's declared
 /// <see cref="Model"/> <see cref="Type"/> is known but <see cref="Model"/> should be copied from the existing
 /// instance e.g. when copying from a base <see cref="ViewDataDictionary"/> instance to a
 /// <see cref="ViewDataDictionary{TModel}"/> instance.
 /// </para>
 /// <para>
 /// This constructor may <c>throw</c> if <c>source.Model</c> is non-<c>null</c> and incompatible with
 /// <paramref name="declaredModelType"/>. Pass <c>model: null</c> to
 /// <see cref="ViewDataDictionary(ViewDataDictionary, object, Type)"/> to ignore <c>source.Model</c>.
 /// </para>
 /// </remarks>
 protected ViewDataDictionary(ViewDataDictionary source, Type declaredModelType)
     : this(source, model : source.Model, declaredModelType : declaredModelType)
 {
 }