Cet article présente principalement les informations pertinentes d'asp.net core mvc pour implémenter en détail la fonction pseudo-statique. Il a une certaine valeur de référence. Les amis intéressés peuvent s'y référer
Dans les grands systèmes de sites Web. Pour améliorer les performances d'accès au système, certains contenus peu fréquents sont souvent publiés sous forme de pages statiques, comme la page de détails des produits du centre commercial et la page de détails des actualités. Une fois ces informations publiées, la fréquence des modifications ne sera pas très élevée si vous les utilisez toujours. S'il est traité via une sortie dynamique, cela entraînera certainement un énorme gaspillage de ressources sur le serveur. Mais nous ne pouvons pas créer indépendamment des pages statiques pour ces contenus, nous pouvons donc utiliser un traitement pseudo-statique dans le système. Quant à ce qu'est le pseudo-statique, vous pouvez le rechercher sur Baidu. Présentons ici comment implémenter le pseudo-statique dans asp.net core mvc.
Dans le framework MVC, la vue représente la vue, et le résultat de son exécution est le contenu finalement envoyé au navigateur client, y compris html, css, js, etc. Si nous voulons obtenir la statique, nous devons enregistrer le résultat de l'exécution de la vue en tant que fichier statique et l'enregistrer dans un emplacement spécifié, tel qu'un disque, un cache distribué, etc., afin de pouvoir lire directement le contenu enregistré la prochaine fois. accédez-y. Pas besoin d’exécuter à nouveau la logique métier. Alors, que devrait faire asp.net core mvc pour obtenir une telle fonction ? La réponse est d'utiliser des filtres. Dans le framework MVC, plusieurs types de filtres sont fournis. Ici, nous allons utiliser des filtres d'action qui fournissent deux moments : avant l'exécution de l'action et après l'exécution de l'action. Nous pouvons d'abord déterminer si la page statique a été générée avant l'exécution de l'action. Si elle a été générée, nous pouvons directement lire le contenu du fichier et le sortir, et la logique suivante sera ignorée. S'il n'y a pas de production, continuez à descendre, capturez les résultats à ce stade une fois l'action exécutée, puis enregistrez le contenu statique généré par les résultats.
Venons-en ensuite au code d'implémentation spécifique. Nous définissons d'abord un type de filtre, que nous appelons StaticFileHandlerFilterAttribute. Cette classe est dérivée du ActionFilterAttribute fourni dans le framework. OnActionExecuted (Après l'exécution de l'action), OnActionExecuting (avant l'exécution de l'action), le code spécifique est le suivant :
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public class StaticFileHandlerFilterAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext context){} public override void OnActionExecuting(ActionExecutingContext context){} }
Dans OnActionExecuting, vous Il faut déterminer si le contenu statique a été généré. Si un contenu de sortie directe a été généré, l'implémentation logique est la suivante :
//按照一定的规则生成静态文件的名称,这里是按照area+"-"+controller+"-"+action+key规则生成 string controllerName = context.RouteData.Values["controller"].ToString().ToLower(); string actionName = context.RouteData.Values["action"].ToString().ToLower(); string area = context.RouteData.Values["area"].ToString().ToLower(); //这里的Key默认等于id,当然我们可以配置不同的Key名称 string id = context.RouteData.Values.ContainsKey(Key) ? context.RouteData.Values[Key].ToString() : ""; if (string.IsNullOrEmpty(id) && context.HttpContext.Request.Query.ContainsKey(Key)) { id = context.HttpContext.Request.Query[Key]; } string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string.IsNullOrEmpty(id) ? "" : ("-" + id)) + ".html"); //判断文件是否存在 if (File.Exists(filePath)) { //如果存在,直接读取文件 using (FileStream fs = File.Open(filePath, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) { //通过contentresult返回文件内容 ContentResult contentresult = new ContentResult(); contentresult.Content = sr.ReadToEnd(); contentresult.ContentType = "text/html"; context.Result = contentresult; } } }
Dans OnActionExecuted, nous avons besoin du résultat de l'action pour déterminer si le type de résultat de l'action est un ViewResult. Si le résultat est exécuté via du code, le résultat est obtenu et une page statique est générée selon les mêmes règles que ci-dessus.
//获取结果 IActionResult actionResult = context.Result; //判断结果是否是一个ViewResult if (actionResult is ViewResult) { ViewResult viewResult = actionResult as ViewResult; //下面的代码就是执行这个ViewResult,并把结果的html内容放到一个StringBuiler对象中 var services = context.HttpContext.RequestServices; var executor = services.GetRequiredService<ViewResultExecutor>(); var option = services.GetRequiredService<IOptions<MvcViewOptions>>(); var result = executor.FindView(context, viewResult); result.EnsureSuccessful(originalLocations: null); var view = result.View; StringBuilder builder = new StringBuilder(); using (var writer = new StringWriter(builder)) { var viewContext = new ViewContext( context, view, viewResult.ViewData, viewResult.TempData, writer, option.Value.HtmlHelperOptions); view.RenderAsync(viewContext).GetAwaiter().GetResult(); //这句一定要调用,否则内容就会是空的 writer.Flush(); } //按照规则生成静态文件名称 string area = context.RouteData.Values["area"].ToString().ToLower(); string controllerName = context.RouteData.Values["controller"].ToString().ToLower(); string actionName = context.RouteData.Values["action"].ToString().ToLower(); string id = context.RouteData.Values.ContainsKey(Key) ? context.RouteData.Values[Key].ToString() : ""; if (string.IsNullOrEmpty(id) && context.HttpContext.Request.Query.ContainsKey(Key)) { id = context.HttpContext.Request.Query[Key]; } string devicedir = Path.Combine(AppContext.BaseDirectory, "wwwroot", area); if (!Directory.Exists(devicedir)) { Directory.CreateDirectory(devicedir); } //写入文件 string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string.IsNullOrEmpty(id) ? "" : ("-" + id)) + ".html"); using (FileStream fs = File.Open(filePath, FileMode.Create)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8)) { sw.Write(builder.ToString()); } } //输出当前的结果 ContentResult contentresult = new ContentResult(); contentresult.Content = builder.ToString(); contentresult.ContentType = "text/html"; context.Result = contentresult; }
Clé mentionnée ci-dessus, on ajoute directement l'attribut correspondant
public string Key { get;set; }
Nous pouvons donc utiliser ce filtre, la méthode d'utilisation : dans le contrôleur ou la méthode du contrôleur Ajoutez la fonctionnalité [StaticFileHandlerFilter] Si vous souhaitez configurer différentes clés, vous pouvez utiliser [StaticFileHandlerFilter(Key="set value")]<. 🎜>
La statique a été mise en œuvre. Nous devons encore envisager les mises à jour. Si l'arrière-plan Après la mise à jour d'un article, nous devons également mettre à jour la page statique. Il existe de nombreuses solutions : l'une consiste à supprimer la page statique correspondante de manière synchrone. le contenu est mis à jour en arrière-plan. Nous en introduisons ici une autre, la mise à jour programmée, ce qui signifie que la page statique a une certaine période de validité et est automatiquement mise à jour après cette période de validité. Pour implémenter cette logique, nous devons obtenir l'heure de création de la page statique dans la méthode OnActionExecuting, puis la comparer avec l'heure actuelle pour déterminer si elle a expiré. Si elle n'a pas expiré, le contenu sera affiché directement si. il a expiré, continuez à exécuter la logique suivante. Le code spécifique est le suivant ://获取文件信息对象 FileInfo fileInfo=new FileInfo(filePath); //结算时间间隔,如果小于等于两分钟,就直接输出,当然这里的规则可以改 TimeSpan ts = DateTime.Now - fileInfo.CreationTime; if(ts.TotalMinutes<=2) { using (FileStream fs = File.Open(filePath, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) { ContentResult contentresult = new ContentResult(); contentresult.Content = sr.ReadToEnd(); contentresult.ContentType = "text/html"; context.Result = contentresult; } } }