2016-08-03 71 views
2

我想在ASP.NET Core MVC中使用ICompositeViewEngine替换System.Web.Mvc中的ViewEngine,因为它在.NET Core中不再可用。我通常试图在此项目中将Webform从ASP.NET迁移到ASP.NET Core。Resolver或ServiceProvider对使用ICompositeViewEngine所需的依赖关系

我发现了以下解决方案:Where are the ControllerContext and ViewEngines properties in MVC 6 Controller?我相信这可能会解决我的问题。在github问题中,我还发现了一个与ServiceProvider类似的引擎创建:https://github.com/aspnet/Mvc/issues/3091

但是,我不确定我可能会错过哪些依赖关系或框架,因为我对.NET非常陌生。我有以下命名空间:

using Microsoft.AspNetCore.Mvc; 
using Microsoft.AspNetCore.Mvc.ViewEngines; 
using Microsoft.AspNetCore.Mvc.ViewFeatures; 
using Microsoft.Extensions.DependencyInjection; 

我相信可能与我的问题有关。

我原来的代码是:

public static string RenderPartialToString(Controller controller, string viewName, object model) 
    { 
     controller.ViewData.Model = model; 

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

      return "document.write('" + sw.GetStringBuilder().Replace('\n', ' ').Replace('\r', ' ').Replace("'","\\'").ToString() + "');"; 
     } 
    } 

,现在我尝试使用以下任一:

var engine = Resolver.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; 
var engine2 = IServiceProvider.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; 

我在正确的轨道上解决这一问题?是否有更简单的方法来取代.NET Core中的System.Web.Mvc ViewEngines?我需要修复“”在当前上下文中是否存在“Resolver和/或ServiceProvider错误?

谢谢。我希望我能够遵循问题指南。

编辑:请让我知道如果我应该包括我的代码中的这个问题的任何其他内容。我目前正在阅读有关依赖注入以更好地了解情况。

回答

4

你主要是在正确的轨道上。 ASP.NET核心摆脱了许多静态对象,所以你不能做像Resolver.GetService这样的事情。 Resolver不存在。相反,请使用dependency injection系统。

如果你只是需要从控制器访问ICompositeViewEngine,注入它在构造函数中:如果你想有一个处理剃刀到字符串呈现离散的服务

public MyController(ICompositeViewEngine viewEngine) 
{ 
    // save a reference to viewEngine 
} 

,你需要在启动时注册它:

public void ConfigureServices(IServiceCollection services) 
{ 
    // (Other code...) 

    services.AddTransient<IViewRenderingService, ViewRenderingService>(); 

    services.AddMvc(); 
} 

本身看起来像这样的服务:

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

public interface IViewRenderingService 
{ 
    string RenderPartialView(ActionContext context, string name, object model = null); 
} 

public class ViewRenderingService : IViewRenderingService 
{ 
    private readonly ICompositeViewEngine _viewEngine; 
    private readonly ITempDataProvider _tempDataProvider; 

    public ViewRenderingService(ICompositeViewEngine viewEngine, ITempDataProvider tempDataProvider) 
    { 
     _viewEngine = viewEngine; 
     _tempDataProvider = tempDataProvider; 
    } 

    public string RenderPartialView(ActionContext context, string name, object model) 
    { 
     var viewEngineResult = _viewEngine.FindView(context, name, false); 

     if (!viewEngineResult.Success) 
     { 
      throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", name)); 
     } 

     var view = viewEngineResult.View; 

     using (var output = new StringWriter()) 
     { 
      var viewContext = new ViewContext(
       context, 
       view, 
       new ViewDataDictionary(
        new EmptyModelMetadataProvider(), 
        new ModelStateDictionary()) 
       { 
        Model = model 
       }, 
       new TempDataDictionary(
        context.HttpContext, 
        _tempDataProvider), 
       output, 
       new HtmlHelperOptions()); 

      view.RenderAsync(viewContext).GetAwaiter().GetResult(); 

      return output.ToString(); 
     } 
    } 
} 

要从控制器使用它,注入并调用它:如果你想使用剃刀MVC以外的全部,看this answer

public class HomeController : Controller 
{ 
    private readonly IViewRenderingService _viewRenderingService; 

    public HomeController(IViewRenderingService viewRenderingService) 
    { 
     _viewRenderingService = viewRenderingService; 
    } 

    public IActionResult Index() 
    { 
     var result = _viewRenderingService.RenderPartialView(ControllerContext, "PartialViewName", model: null); 
     // do something with the string 

     return View(); 
    } 
} 

+0

我真的很感谢您的回答,但我应该使用这些类/方法的引用/名称空间? –

+0

@KemalTezerDilsiz向示例服务代码添加了名称空间。这有帮助吗? –

+0

问题是我在公共静态类中使用ViewEngine。它被称为Utils并且有两个方法,RenderPartialToString就是我试图修改的一个方法。如果它不是一个静态构造函数,我相信这会起作用。有什么建议么?我应该尝试重组我的项目吗? –