MVC 4:从字符串而不是从文件路径创建新的Razor View

时间:2015-11-11 04:00:14

标签: c# asp.net-mvc asp.net-mvc-4 razor

目前从代码创建Razor View的方法是使用路径参数查找文件。

RazorView viewResult = new RazorView(ControllerContext, viewPath, layoutPath, boolRunViewStartPages, IEnumerableViewStartFileExtensions);

我不想从文件中获取视图,我想从我的数据库字符串中获取视图。我怎样才能做到这一点:

RazorView viewResult = new RazorView(ControllerContext, stringViewHtml);

我不想使用虚拟路径提供程序,因为它会改变我的所有路由系统,但是如果有一种方法我只能在创建剃刀视图时激活VPP,我们将不胜感激! /强>

1 个答案:

答案 0 :(得分:1)

自从我得到解决方案以来已经有一段时间了,我将在这里分享:

    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);
    }
}