How to intercept view rendering to add HTML/JS on all partial views?

前端 未结 2 1870
太阳男子
太阳男子 2020-12-30 06:58

I need to write the contents of a js file from a convention-driven location (like ~/ClientApp/Controllers/Home/Home.js if loading the view located at ~/Views/Home/Home.cshtm

2条回答
  •  猫巷女王i
    2020-12-30 07:55

    You could write a custom view:

    public class MyRazorView : RazorView
    {
        public MyRazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable viewStartFileExtensions, IViewPageActivator viewPageActivator)
            : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions, viewPageActivator)
        {
    
        }
    
        protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
        {
            base.RenderView(viewContext, writer, instance);
    
            var view = (BuildManagerCompiledView)viewContext.View;
            var context = viewContext.HttpContext;
            var path = context.Server.MapPath(view.ViewPath);
            var viewName = Path.GetFileNameWithoutExtension(path);
            var controller = viewContext.RouteData.GetRequiredString("controller");
            var js = context.Server.MapPath(
                string.Format(
                    "~/ClientApp/Controllers/{0}/{0}.{1}.js",
                    viewName,
                    controller
                )
            );
            if (File.Exists(js))
            {
                writer.WriteLine(
                    string.Format(
                        "",
                        File.ReadAllText(js)
                    )
                );
            }
        }
    }
    

    and a custom view engine which will return this custom view when a partial view is to be requested:

    public class MyRazorViewEngine : RazorViewEngine
    {
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new MyRazorView(
                controllerContext, 
                partialPath, 
                null, 
                false, 
                base.FileExtensions, 
                base.ViewPageActivator
            );
        }
    }
    

    which would be registered in Application_Start:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
    
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new MyRazorViewEngine());
    }
    

    You probably might need to adjust some of the paths as it was not quite clear in your question where exactly should the js be located but normally you should have enough details in the answer.

提交回复
热议问题