MVC 4:从字符串而不是从文件路径创建新的Razor视图
本文关键字:创建 路径 Razor 文件 视图 字符串 MVC | 更新日期: 2023-09-27 18:21:23
从当前代码创建Razor视图的方法是使用路径参数查找文件。
RazorView viewResult = new RazorView(ControllerContext, viewPath, layoutPath, boolRunViewStartPages, IEnumerableViewStartFileExtensions);
我不想从文件中获取视图,我想从数据库字符串中获取视图。我如何才能做到这一点:
RazorView viewResult = new RazorView(ControllerContext, stringViewHtml);
我不想使用虚拟路径提供商,因为它会改变我的所有路由系统,但如果有一种方法,我只能在创建剃刀视图时激活VPP,我将不胜感激
我已经有一段时间没有得到解决方案了,我将在这里分享:
public static string RenderRazorViewToString(string viewToRender, object model, string controllerName, string loadAction, HttpContextBase httpContext, List<FormViewBags> viewData, string formModelType)
{
string view = "";
//Creating the view data
ViewDataDictionary ViewData = new ViewDataDictionary();
//The type of model used for this view
Type modelType = Helper.GetModelType(formModelType);
//Compiling the object model from parameter with the correct type
ViewData.Model = Cast(model, modelType);
if ((ViewData.Model != null) && (viewData != null))
{
//Adding view bags for the view
foreach (FormViewBags item in viewData)
{
ViewData.Add(item.Key, item.Value);
}
}
//The controller used to all this view
Type controllerType = Helper.GetModelType(controllerName);
//Creating the controller
object controller = Activator.CreateInstance(controllerType);
//Setting the routing
RouteData rd = new System.Web.Routing.RouteData();
rd.Values.Add("controller", controllerName.Split('.').Last().Replace("Controller",""));
//rd.Values.Add("action", loadAction);
//Setting the controller with corresponding context
((ControllerBase)(controller)).ControllerContext = new ControllerContext(httpContext, rd, (ControllerBase)controller);
ControllerContext cc = ((ControllerBase)(controller)).ControllerContext;
using (var sw = new StringWriter())
{
//The custom view engine I used to get the view
var engine = ViewEngines.Engines.Where(s => s.ToString().Equals("MyApp.App_Start.CustomViewEngine")).SingleOrDefault();
if (engine == null) throw new Exception("no viewengine");
//Finding the string/text of the view. My website use VPP to get view from database.
var viewResult = engine.FindPartialView(cc, viewToRender, false);
var viewContext = new ViewContext(cc, viewResult.View, ViewData, cc.Controller.TempData, sw);
//This code here renders all the information above into the real compiled string view
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(cc, viewResult.View);
view = sw.GetStringBuilder().ToString();
}
//Returns the string of the compiled view
return view;
}
这是我的自定义视图引擎:
public class CustomViewEngine : RazorViewEngine
{
private List<string> _plugins = new List<string>();
public CustomViewEngine(List<string> pluginFolders)
{
_plugins = pluginFolders;
ViewLocationFormats = GetViewLocations();
MasterLocationFormats = GetMasterLocations();
PartialViewLocationFormats = GetViewLocations();
}
public string[] GetViewLocations()
{
var views = new List<string>();
views.Add("~/Views/{1}/{0}.cshtml");
foreach (string p in _plugins)
{
views.Add("~/Modules/" + p + "/Views/{1}/{0}.cshtml");
}
return views.ToArray();
}
public string[] GetMasterLocations()
{
var masterPages = new List<string>();
masterPages.Add("~/Views/Shared/{0}.cshtml");
foreach (string p in _plugins)
{
masterPages.Add("~/Modules/" + p + "/Views/Shared/{0}.cshtml");
}
return masterPages.ToArray();
}
}
您需要使用VPP(虚拟路径提供商)来自动:
/* VIRTUAL PATH HELPER */
public class ViewPathProvider : VirtualPathProvider
{
//private static FormDBContext dbForm = new FormDBContext();
public override bool FileExists(string virtualPath)
{
return IsExistByVirtualPath(virtualPath) || base.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsExistByVirtualPath(virtualPath))
{
return new ViewFile(virtualPath);
}
return base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsExistByVirtualPath(virtualPath)) {
//return null; //return null to force no cache
return ViewCacheDependencyManager.Instance.Get(virtualPath); //uncomment this to enable caching
}
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override String GetFileHash(String virtualPath, IEnumerable virtualPathDependencies) //uncomment this getfilehash to turn on cache
{
if (IsExistByVirtualPath(virtualPath))
{
return Guid.NewGuid().ToString();
}
return Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
public bool IsExistByVirtualPath(string virtualPath)
{
bool isExist = false;
try
{
string checker = virtualPath.First().Equals('~') ? virtualPath : "~" + virtualPath;
if (checker.IndexOf("/Views/", StringComparison.OrdinalIgnoreCase) > 0)
{
checker = "~" + Helper.RemoveSubfolderName(checker);
}
using (FormDBContext formsDB = new FormDBContext())
{
List<Form> f = formsDB.Forms.Where(m => m.VirtualPath.Equals(checker, StringComparison.CurrentCultureIgnoreCase)).ToList();
if ((f != null) && (f.Count > 0))
{
isExist = true;
base.GetFile(virtualPath);
}
}
}
catch (Exception ex)
{
Helper.Log("Is Exist By Virtual Path: " + ex);
}
return isExist;
}
}
public class VirtualForm
{
//private FormDBContext dbForm = new FormDBContext();
public string GetByVirtualPath(string virtualPath)
{
using (FormDBContext dbForm = new FormDBContext())
{
string content = string.Empty;
string checker = virtualPath.First().Equals("~") ? virtualPath : "~" + virtualPath;
if (checker.IndexOf("/Views/", StringComparison.OrdinalIgnoreCase) > 0)
{
checker = "~" + Helper.RemoveSubfolderName(checker);
}
Form f = dbForm.Forms.Where(m => m.VirtualPath.Equals(checker, StringComparison.CurrentCultureIgnoreCase)).First();
content = f.Html;
return content;
}
}
}
public class ViewFile : VirtualFile
{
private string path;
public ViewFile(string virtualPath)
: base(virtualPath)
{
path = virtualPath;
}
public override Stream Open()
{
if (string.IsNullOrEmpty(path))
return new MemoryStream();
VirtualForm vf = new VirtualForm();
string content = vf.GetByVirtualPath(path);
if (string.IsNullOrEmpty(content))
return new MemoryStream();
return new MemoryStream(ASCIIEncoding.UTF8.GetBytes(content));
}
}
public class ViewCacheDependencyManager
{
private static Dictionary<string, ViewCacheDependency> dependencies = new Dictionary<string, ViewCacheDependency>();
private static volatile ViewCacheDependencyManager instance;
private static object syncRoot = new Object();
private ViewCacheDependencyManager()
{
}
public static ViewCacheDependencyManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new ViewCacheDependencyManager();
}
}
}
return instance;
}
}
public CacheDependency Get(string virtualPath)
{
if (!dependencies.ContainsKey(virtualPath))
dependencies.Add(virtualPath, new ViewCacheDependency(virtualPath));
/*else //This else will always reset cache when it is virtual path
{
dependencies.Remove(virtualPath);
dependencies.Add(virtualPath, new ViewCacheDependency(virtualPath));
}*/
return dependencies[virtualPath];
}
public void Invalidate(string virtualPath)
{
string vp = virtualPath.First().Equals('~') ? virtualPath.Remove(0, 1) : virtualPath;
if (dependencies.ContainsKey(vp))
{
var dependency = dependencies[vp];
dependency.Invalidate();
dependency.Dispose();
dependencies.Remove(vp);
}
}
public void InvalidateAll()
{
dependencies.Clear();
}
}
public class ViewCacheDependency : CacheDependency
{
public ViewCacheDependency(string virtualPath)
{
base.SetUtcLastModified(DateTime.UtcNow);
}
public void Invalidate()
{
base.NotifyDependencyChanged(this, EventArgs.Empty);
}
}