ASP. NET Core Razor generates HTML static files

Source: Internet
Author: User
Tags httpcontext

First, preface

In recent projects, use Util for development, using the Razor write front page. The first use of feeling or is not accustomed to, before the end of the separation of the way developed, but the use of Util package after the development of the Angular sense of efficiency or leverage drops.

Second, the question

In the release code, Webpack packaging exception, hint is missing some Html files, I looked at the corresponding directory, found that the directory is missing some HTML files, and then asked He Xi greatly, the solution is that each page needs to access to generate the corresponding HTML static file. There is a doubt as to whether there is a way to get all the routes, and then simply visit once to generate all the HTML pages.

III. Solution 3.1 Generate HTML per visit

Solution Ideas:

    • Inheritance ActionFilterAttribute attributes, overriding execution methods
    • Access is determined by whether the access is Result ViewResult , if it is to generate HTML
    • RazorViewEnginerender from find to View after
<summary>///generating HTML static file//</summary>public class Htmlattribute:actionfilterattribute {//<summa    Ry>///build path, relative root path, example:/typings/app/app.component.html//</summary> public string Path {get; set;} <summary>///path template, Example: typings/app/{area}/{controller}/{controller}-{action}.component.html//</summ    Ary> public string Template {get; set;} <summary>///execute Generate//</summary> public override async Task Onresultexecutionasync (resultexecut        Ingcontext context, Resultexecutiondelegate next) {await writeviewtofileasync (context); Await base.    Onresultexecutionasync (context, next); }///<summary>//write view to HTML file///</summary> Private async Task Writeviewtofileasync (resultexec            Utingcontext context) {try {var html = await Rendertostringasync (context); if (string.        Isnullorwhitespace (HTML)) return;    var path = Util.Helpers.Common.GetPhysicalPath (string. Isnullorwhitespace (Path)?            GetPath (context): Path);            var directory = System.IO.Path.GetDirectoryName (Path); if (string.            Isnullorwhitespace (directory)) return;            if (directory.exists (directory) = = False) directory.createdirectory (directory);        File.writealltext (path, HTML); } catch (Exception ex) {ex. Log (Log.getlog ().        Caption ("Failed to generate HTML static file")); }}///<summary>//Render View///</summary> protected Async task<string> Rendertostringasyn        C (ResultExecutingContext context) {string viewName = "";        object model = NULL; if (context. result is ViewResult result) {ViewName = result.            ViewName; ViewName = string. Isnullorwhitespace (viewName)? Context. Routedata.values["Action"].            Safestring (): ViewName; Model = result.        Model;   }     var razorviewengine = ioc.create<irazorviewengine> ();        var tempdataprovider = ioc.create<itempdataprovider> ();        var serviceprovider = ioc.create<iserviceprovider> ();        var HttpContext = new Defaulthttpcontext {requestservices = serviceprovider}; var actioncontext = new Actioncontext (HttpContext, context.        Routedata, New Actiondescriptor ()); using (var StringWriter = new StringWriter ()) {var viewResult = Razorviewengine.findview (Actioncontext, view            Name, True);            if (Viewresult.view = = null) throw new ArgumentNullException ($ "No View found: {viewName}"); var viewdictionary = new Viewdatadictionary (new Emptymodelmetadataprovider (), New Modelstatedictionary ()) {Model = mode            L}; var viewcontext = new ViewContext (Actioncontext, Viewresult.view, Viewdictionary, new Tempdatadictionary (ActionContext .         HttpContext, Tempdataprovider), StringWriter, New Htmlhelperoptions ());   Await ViewResult.View.RenderAsync (viewcontext);        return stringwriter.tostring (); }}///<summary>///Get HTML Default build Path///</summary> protected virtual string GetPath (Resultexecu Tingcontext context) {var area = context. routedata.values["Area"].        Safestring (); var controller = context. routedata.values["Controller"].        Safestring (); var action = context. Routedata.values["Action"].        Safestring (); var path = Template.replace ("{area}", area). Replace ("{controller}", controller).        Replace ("{action}", action); return path.    ToLower (); }}
3.2 One-time access generate all HTML

Solution Ideas:

    • Get all registered routes
    • Get RazorHtml routes that use custom attributes
    • Bypass Routing for API interfaces
    • Build RouteData information to find the RazorViewEngine appropriate view in
    • Build ViewContext to render an HTML string
    • Writes the rendered HTML string to the file

Get all registered routes, here is more important, other places can also be used.

<summary>///Get all routing information///</summary>///<returns></returns>public ienumerable< Routeinformation> getallrouteinformations () {list<routeinformation> List = new list<routeinformation>    ();    var actiondescriptors = This._actiondescriptorcollectionprovider.actiondescriptors.items;        foreach (Var actiondescriptor in actiondescriptors) {routeinformation info = new Routeinformation (); if (ActionDescriptor.RouteValues.ContainsKey ("area")) {info.        AreaName = actiondescriptor.routevalues["area"]; }//Razor page path and call if (Actiondescriptor is Pageactiondescriptor pageactiondescriptor) {in Fo.            Path = Pageactiondescriptor.viewenginepath; Info.        invocation = Pageactiondescriptor.relativepath; }//Route property path if (actiondescriptor.attributerouteinfo! = null) {info.        Path = $ "/{actiondescriptor.attributerouteinfo.template}"; }//COntroller/action Path and call if (Actiondescriptor is Controlleractiondescriptor controlleractiondescriptor) { if (info. Path.isempty ()) {info.            Path = $ "/{controlleractiondescriptor.controllername}/{controlleractiondescriptor.actionname}"; } var controllerhtmlattribute = Controlleractiondescriptor.controllertypeinfo.getcustomattribute<razorh            Tmlattribute> (); if (Controllerhtmlattribute! = null) {info.                FilePath = Controllerhtmlattribute.path; Info.            TemplatePath = controllerhtmlattribute.template;            } var Htmlattribute = controlleractiondescriptor.methodinfo.getcustomattribute<razorhtmlattribute> (); if (Htmlattribute! = null) {info.                FilePath = Htmlattribute.path; Info.            TemplatePath = htmlattribute.template; } info. Controllername = ControlleractiondescRiptor.            Controllername; Info.            ActionName = Controlleractiondescriptor.actionname; Info. Invocation = $ "{Controlleractiondescriptor.controllername}controller.        {Controlleractiondescriptor.actionname} "; } info.        Invocation + = $ "({actiondescriptor.displayname})"; List.    ADD (info); } return list;}

Generating HTML static files

<summary>///Generate HTML file///</summary>///<returns></returns>public async Task Generate () {fo Reach (Var routeinformation in _routeanalyzer.getallrouteinformations ()) {//skips the processing of the API if (Routeinformati On.        Path.startswith ("/api")) {continue;    } await Writeviewtofileasync (routeinformation); }}///<summary>///render View As String//</summary>///<param name= "INFO" > Routing information </param>///<returns ></returns>public Async task<string> Rendertostringasync (routeinformation info) {var razorViewEngine =    Ioc.create<irazorviewengine> ();    var tempdataprovider = ioc.create<itempdataprovider> ();    var serviceprovider = ioc.create<iserviceprovider> ();    var routedata = new Routedata (); if (!info. Areaname.isempty ()) {RouteData.Values.Add ("area", info.)    AreaName); } if (!info. Controllername.isempty ()) {ROUTEDATA.VALUES.ADD ("controller", info. ControllerName); } if (!info. Actionname.isempty ()) {ROUTEDATA.VALUES.ADD ("action", info.    ActionName);    } var httpcontext = new Defaulthttpcontext {requestservices = serviceprovider};    var actioncontext = new Actioncontext (HttpContext, Routedata, New Actiondescriptor ()); var viewResult = Razorviewengine.findview (Actioncontext, info.    ActionName, True); if (!viewresult.success) {throw new InvalidOperationException ($) cannot find the view template {info.    ActionName} "); } using (var StringWriter = new StringWriter ()) {var viewdictionary = new Viewdatadictionary (New Emptymodelm        Etadataprovider (), New Modelstatedictionary ()); var viewcontext = new ViewContext (Actioncontext, Viewresult.view, Viewdictionary, New Tempdatadictionary (        Actioncontext.httpcontext, Tempdataprovider), StringWriter, New Htmlhelperoptions ());        Await ViewResult.View.RenderAsync (viewcontext);    return stringwriter.tostring (); }}///<summary>///Write a view to a file///</summary>/// <param name= "INFO" > Routing information </param>///<returns></returns>public async Task        Writeviewtofileasync (routeinformation info) {try {var html = await Rendertostringasync (info); if (string.        Isnullorwhitespace (HTML)) return; var path = Utils.Helpers.Common.GetPhysicalPath (string. Isnullorwhitespace (info. FilePath)? GetPath (info): info.        FilePath);        var directory = System.IO.Path.GetDirectoryName (Path); if (string.        Isnullorwhitespace (directory)) return;        if (directory.exists (directory) = = False) directory.createdirectory (directory);    File.writealltext (path, HTML); } catch (Exception ex) {ex. Log (Log.getlog ().    Caption ("Failed to generate HTML static file")); }}protected Virtual String GetPath (routeinformation info) {var area = info.    Areaname.safestring (); var controller = info.    Controllername.safestring (); var action = info.    Actionname.safestring (); var path = info. Templatepath.replace ("{isA} ", area). Replace ("{controller}", controller).    Replace ("{action}", action); return path. ToLower ();}
Iv. Mode of Use
    • MVC Controller Configuration

    • Startup configuration

    • One-time generation method, call an interface can

Five, the source address

Util
Bing.netcore
Razor generating static HTML files: Https://github.com/dotnetcore/Util/tree/master/src/Util.Webs/Razors or https://github.com/ Bing-framework/bing.netcore/tree/master/src/bing.webs/razors

Vi. references

Get all registered routes: Https://github.com/kobake/AspNetCore.RouteAnalyzer

ASP. NET Core Razor generates HTML static files

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.