Dónde están los ControllerContext y ViewEngines propiedades en MVC 6 Controlador?

He creado un nuevo MVC6 proyecto y la construcción de un nuevo sitio. El objetivo es conseguir que el resultado representado de una vista. He encontrado el siguiente código, pero yo no puedo ir a trabajar porque no puedo encontrar la ControllerContext y la ViewEngines.

Aquí está el código que desee volver a escribir:

protected string RenderPartialViewToString(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = ControllerContext.RouteData.GetRequiredString("action");

    ViewData.Model = model;

    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}
  • es este código dentro de un controlador? ViewEngines y ControllerContext están en el Sistema.Web.Mvc.. ControllerBase también tiene una propiedad de ControllerContext
  • Esto es para MVC6 no tiene estos.
  • no importa.. necesitan etiquetar mis proyectos de ejemplo mejor 🙂
InformationsquelleAutor Martijn | 2015-08-09

4 Kommentare

  1. 22

    Actualización: estoy actualizando esta para trabajar .Net Core 2.x como la Api han cambiado desde 2015!

    Primero de todo, podemos aprovechar el integrado en la inyección de dependencia que viene con ASP.Net MVC Núcleo el cual nos dará la ICompositeViewEngine objeto que se necesita para el procesamiento de nuestros puntos de vista de forma manual. Así, por ejemplo, un controlador tendría este aspecto:

    public class MyController : Controller
    {
        private ICompositeViewEngine _viewEngine;
    
        public MyController(ICompositeViewEngine viewEngine)
        {
            _viewEngine = viewEngine;
        }
    
        //Rest of the controller code here
    }

    A continuación, el código que necesitamos realmente para representar una vista. Tenga en cuenta que es ahora es un async método como vamos a estar haciendo llamadas asincrónicas internamente:

    private async Task<string> RenderPartialViewToString(string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.ActionDescriptor.ActionName;
    
        ViewData.Model = model;
    
        using (var writer = new StringWriter())
        {
            ViewEngineResult viewResult = 
                _viewEngine.FindView(ControllerContext, viewName, false);
    
            ViewContext viewContext = new ViewContext(
                ControllerContext, 
                viewResult.View, 
                ViewData, 
                TempData, 
                writer, 
                new HtmlHelperOptions()
            );
    
            await viewResult.View.RenderAsync(viewContext);
    
            return writer.GetStringBuilder().ToString();
        }
    }

    Y llamar al método, es tan simple como esto:

    public async Task<IActionResult> Index()
    {
        var model = new TestModel
        {
            SomeProperty = "whatever"
        }
    
        var renderedView = await RenderPartialViewToString("NameOfView", model);
    
        //Do what you want with the renderedView here
    
        return View();
    }
    • Gracias. ¿Cómo te diste cuenta? Tengo la sensación de que usted cavó en esto. Y funciona, por cierto, gracias de nuevo 🙂
    • Sí, yo tenía una cavar a su alrededor. Tomó un tiempo, pero pensé que sería útil para mí de todos modos.
    • Puedo preguntarte donde cavó alrededor? He tratado de encontrar a mí mismo offcourse, pero no pude encontrar mucho en Google sobre este tema.
    • He jugado con la aplicación de ejemplo, por un tiempo, luego volvió a mirar el código fuente en GitHub. Entonces cuando se me ocurrió que DI fue una parte enorme de MVC6, eché un vistazo a lo que los elementos habían sido puestos en la lista de servicios disponibles y encontrar el compuesto motor de la vista!
    • Sólo una nota que en el núcleo 2 de la ICompositeViewEngine ya no contiene FindPartialView 🙁 así que muchos de los cambios recientes…
    • Supongo que voy a tener que buscar la actualización de este para .Net Core 2. No creo que esto funciona bien para 1!
    • No tomó mucho tiempo para arreglarlo 🙂
    • Es posible generalizar este método (fuera de la acción del controlador) para obtener una cadena html por que acaban de pasar el .cshtml la vista y el modelo y la misma cadena html que pueden ser enviados como cuerpo del correo electrónico o de otros muchos escenarios de aplicación.
    • Hay una significativa manera de hacer esto sin tener que inyectar ICompositeViewEngine? Tengo esto como un método protegido en el interior de un BaseController de que todos mis otros controladores de heredar para que yo pueda acceder a ella desde cualquier controlador. Odio la idea de tener que modificar los constructores de cada controlador en mi solución sólo para que yo pueda inyectar ICompositeViewEngine. Esta DI todo obsesión ha ido demasiado lejos.

  2. 14

    La libertad de dotnet núcleo de 1.0 ha cambiado, esta versión de el código anterior funciona con 1.0 RTM.

    protected string RenderPartialViewToString(string viewName, object model)
    {
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.ActionDescriptor.DisplayName;
    
        ViewData.Model = model;
    
        using (StringWriter sw = new StringWriter())
        {
            var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; //Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
            ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
    
            ViewContext viewContext = new ViewContext(
                ControllerContext,
                viewResult.View,
                ViewData,
                TempData,
                sw,
                new HtmlHelperOptions() //Added this parameter in
            );
    
            //Everything is async now!
            var t = viewResult.View.RenderAsync(viewContext);
            t.Wait();
    
            return sw.GetStringBuilder().ToString();
        }
    }

    Estas usando son necesarios para que este código se compile:

    using System.IO;
    using Microsoft.AspNetCore.Mvc.ViewEngines;
    using Microsoft.AspNetCore.Mvc.ViewFeatures;

    También he tenido que añadir un DI de interfaces para el controlador constructor:

    IServiceProvider serviceProvider

    Mi cuenta constructor se ve como esta ahora:

    public AccountController(
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        IEmailSender emailSender,
        ISmsSender smsSender,
        ILoggerFactory loggerFactory,
        IServiceProvider serviceProvider)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _smsSender = smsSender;
        _logger = loggerFactory.CreateLogger<AccountController>();
        _serviceProvider = serviceProvider;
    }
    • Estoy recibiendo «El nombre de ‘ViewData’ no existe en el contexto actual» con el proporcionado referencias. Mismo para TempData.
    • También, lo que sería un cambio necesario para hacer de esto un servicio general, el uso de la inyección de dependencia en lugar de un método para un solo controlador?
  3. 2

    La solución proporcionada por Martin Tomos trabajado para mí, pero he tenido que cambiar:

    ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);

    con

    ViewEngineResult viewResult = engine.GetView(_env.WebRootPath, viewName, false);

    También en el controlador de constructor tenido que añadir

    private IHostingEnvironment _env;
    
    public AccountController(IHostingEnvironment env)
    {
        _env = env;
    }
  4. 1

    Solución por Martin Tomos funciona bien. Mis cambios: se ha eliminado serviceProvider y obtener ICompositeViewEngine en el constructor de la via DI.
    Constructor parece:

    private readonly ICompositeViewEngine _viewEngine;
    
            public AccountController(
    
                    UserManager<ApplicationUser> userManager,
                    SignInManager<ApplicationUser> signInManager,
                    IEmailSender emailSender,
                    ISmsSender smsSender,
                    ILoggerFactory loggerFactory,
                    ICompositeViewEngine viewEngine)
                {
                    _userManager = userManager;
                    _signInManager = signInManager;
                    _emailSender = emailSender;
                    _smsSender = smsSender;
                    _logger = loggerFactory.CreateLogger<AccountController>();
                    _viewEngine = viewEngine;;
                }

    y poner

    ViewEngineResult viewResult = _viewEngine.FindView(ControllerContext, viewName, false);

    lugar de

    var engine = _serviceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; //Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
    ViewEngineResult viewResult = engine.FindView(ControllerContext, viewName, false);
    • Buen toque! La utilizan. Gracias Proggear.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea