Asp.Net Core 之 @Html.Action 迁移

﹥>﹥吖頭↗ 提交于 2020-08-13 18:36:12
原文: Asp.Net Core 之 @Html.Action 迁移

想必只要 接触了 net core的小伙伴们 已经发现 @html.Action()方法 官方已经不提供支持了,转而使用 ViewComponents替代了,同时也增加了TagHelper。但是 如果想用以前的@Html.Action()方法,我们其实可以自己动手去实现它。

下面就开始 实现之旅吧!

1、创建 静态类 HtmlHelperViewExtensions,其命名空间为  Microsoft.AspNetCore.Mvc.Rendering。这样我们直接用@Html直接可以 使用Action方法了。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Threading.Tasks;
 
namespace Microsoft.AspNetCore.Mvc.Rendering
{
     public static class HtmlHelperViewExtensions
     {
         public static IHtmlContent Action( this IHtmlHelper helper, string action, object parameters = null )
         {
             var controller = ( string )helper.ViewContext.RouteData.Values[ "controller" ];
 
             return Action(helper, action, controller, parameters);
         }
 
         public static IHtmlContent Action( this IHtmlHelper helper, string action, string controller, object parameters = null )
         {
             var area = ( string )helper.ViewContext.RouteData.Values[ "area" ];
 
             return Action(helper, action, controller, area, parameters);
         }
 
         public static IHtmlContent Action( this IHtmlHelper helper, string action, string controller, string area, object parameters = null )
         {
             if (action == null )
                 throw new ArgumentNullException( "action" );
 
             if (controller == null )
                 throw new ArgumentNullException( "controller" );
 
 
             var task = RenderActionAsync(helper, action, controller, area, parameters);
 
             return task.Result;
         }
 
         private static async Task<IHtmlContent> RenderActionAsync( this IHtmlHelper helper, string action, string controller, string area, object parameters = null )
         {
             // fetching required services for invocation
             var serviceProvider = helper.ViewContext.HttpContext.RequestServices;
             var actionContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>();
             var httpContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IHttpContextAccessor>();
             var actionSelector = serviceProvider.GetRequiredService<IActionSelector>();
 
             // creating new action invocation context
             var routeData = new RouteData();
             foreach ( var router in helper.ViewContext.RouteData.Routers)
             {
                 routeData.PushState(router, null , null );
             }
             routeData.PushState( null , new RouteValueDictionary( new { controller = controller, action = action, area = area }), null );
             routeData.PushState( null , new RouteValueDictionary(parameters ?? new { }), null );
 
             //get the actiondescriptor
             RouteContext routeContext = new RouteContext(helper.ViewContext.HttpContext) { RouteData = routeData };
             var candidates = actionSelector.SelectCandidates(routeContext);
             var actionDescriptor = actionSelector.SelectBestCandidate(routeContext, candidates);
 
             var originalActionContext = actionContextAccessor.ActionContext;
             var originalhttpContext = httpContextAccessor.HttpContext;
             try
             {
                 var newHttpContext = serviceProvider.GetRequiredService<IHttpContextFactory>().Create(helper.ViewContext.HttpContext.Features);
                 if (newHttpContext.Items.ContainsKey( typeof (IUrlHelper)))
                 {
                     newHttpContext.Items.Remove( typeof (IUrlHelper));
                 }
                 newHttpContext.Response.Body = new MemoryStream();
                 var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
                 actionContextAccessor.ActionContext = actionContext;
                 var invoker = serviceProvider.GetRequiredService<IActionInvokerFactory>().CreateInvoker(actionContext);
                 await invoker.InvokeAsync();
                 newHttpContext.Response.Body.Position = 0;
                 using ( var reader = new StreamReader(newHttpContext.Response.Body))
                 {
                     return new HtmlString(reader.ReadToEnd());
                 }
             }
             catch (Exception ex)
             {
                 return new HtmlString(ex.Message);
             }
             finally
             {
                 actionContextAccessor.ActionContext = originalActionContext;
                 httpContextAccessor.HttpContext = originalhttpContext;
                 if (helper.ViewContext.HttpContext.Items.ContainsKey( typeof (IUrlHelper)))
                 {
                     helper.ViewContext.HttpContext.Items.Remove( typeof (IUrlHelper));
                 }
             }
         }
     }
}

  

2、 在Startup中的 ConfigureServices 方法添加:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor();

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

(备注:因为net core 默认不将IHttpContextAccessor,IActionContextAccessor 依赖注入,所以需要手动进行依赖注入)

3、在页面中,我们就可以直接用 @Html.Action()方法 直接请求 控制器的方法了。          

4、小结:如今微软官方已经提供了 新的 TagHelper、View components 来替代之前的写法。这个教程只适用于对视图层不想做更变的小伙伴使用。如果 是新项目的,还是建议使用 View components!

转自:https://blog.csdn.net/huanghuangtongxue/article/details/78987833

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!