某些情况下,我们需要获取MVC Razor模板生成的字符串,比如,作为发送邮件的内容等等。这时,需要获取生成的内容,下面的代码可以帮助实现这个需求:
using System.IO;
using System.Web.Mvc;
namespace RazorHelper
{
public class RenderHelper
{
public static string RenderViewToString(ControllerContext context, string viewPath, object model = null, bool partial = false)
{
// first find the ViewEngine for this view
ViewEngineResult viewEngineResult = null;
if (partial)
viewEngineResult = ViewEngines.Engines.FindPartialView(context, viewPath);
else
viewEngineResult = ViewEngines.Engines.FindView(context, viewPath, null);
if (viewEngineResult == null)
throw new FileNotFoundException("View cannot be found.");
// get the view and attach the model to view data
var view = viewEngineResult.View;
context.Controller.ViewData.Model = model;
string result = null;
using (var sw = new StringWriter())
{
var ctx = new ViewContext(context, view, context.Controller.ViewData, context.Controller.TempData, sw);
view.Render(ctx, sw);
result = sw.ToString();
}
return result;
}
}
}
这里的关键是要有ControllerContext,这个对象是框架根据上下文生成的,也可以自己创建,下面这段代码创建了一般类型的控制器上下文:
public static T CreateController<T>(RouteData routeData = null) where T : Controller, new()
{
// create a disconnected controller instance
T controller = new T();
// get context wrapper from HttpContext if available
HttpContextBase wrapper;
if (System.Web.HttpContext.Current != null)
wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
else
throw new InvalidOperationException("Can't create Controller Context if no active HttpContext instance is available.");
if (routeData == null)
routeData = new RouteData();
// add the controller routing if not existing
if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller"))
routeData.Values.Add("controller", controller.GetType().Name.ToLower().Replace("controller", ""));
controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
return controller;
}
使用时是这样的:
var controller = ViewRenderer.CreateController<GenericController>();
从上面控制器创建的代码可以看出,关键是需要根据System.Web.HttpContext.Current 创建相关的上下文环境,也就是说,这种方式不适用于脱离Web环境的场景,比如控制台程序或者后台应用等。
网友评论