Fra*_*llo 38 c# asp.net-mvc razor asp.net-core
@Html.ActionAsp.net Core 在哪里?我可以看到@Html.ActionLink但不像以前那样直接调用Action.
它被ViewComponents取代了吗?
Kir*_*lla 30
是的,ViewComponents将是这样做的新方式,但它们与以前的做法并不完全相同@Html.Action...例如,在MVC5和之前,调用"子动作"也会执行任何过滤器(例如,如果控制器在它们上面装饰了过滤器)给它们作为常规动作的外观......但是ViewComponents不是这样,它们是在实际请求的上下文中执行的......
有关视图组件的更多信息:https: //docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components
Yep*_*kai 14
对于asp.net核心2
public class HttpContextAccessor : IHttpContextAccessor
{
private static AsyncLocal<HttpContext> _httpContextCurrent = new AsyncLocal<HttpContext>();
HttpContext IHttpContextAccessor.HttpContext { get => _httpContextCurrent.Value; set => _httpContextCurrent.Value = value; }
}
Run Code Online (Sandbox Code Playgroud)
它基于白羊座的反应.我纠正了没有编译2.0的内容,我添加了几个调整.当前的httpcontext和当前的actioncontext有2个美化的静态值.为httpcontext IHttpContextFactory.Create设置了一个,我在代码中为actioncontext设置了一个.请注意,IActionContextAccessor默认情况下未注册,因此您需要在启动时添加它:IHttpContextAccessor
HttpContext只是一个包装器services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();,所以如果你在一个中改变一些东西,它也会在另一个中改变...我在try/catch的finally中重置我所知道的东西.
我services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();从Items缓存中删除了,因为即使构建urlHelper的actionContext不同(HttpContext.Features),该值也将被重用.
Asp.net核心2.0假设你不会这样做,很有可能还有其他缓存的东西,所以我建议在使用它时要小心,如果你不需要,就不要这样做.
小智 12
ViewComponents很棒,但对于Ajax来说并不是那么好.
如果你真的错过了@ Html.RenderAction方法,那么这是我为AspNetCore一起进行的快速实现.
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;
namespace Microsoft.AspNetCore.Mvc.Rendering {
public static class HtmlHelperViewExtensions
{
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, object parameters = null)
{
var controller = (string)helper.ViewContext.RouteData.Values["controller"];
return RenderAction(helper, action, controller, parameters);
}
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, object parameters = null)
{
var area = (string)helper.ViewContext.RouteData.Values["area"];
return RenderAction(helper, action, controller, area, parameters);
}
public static IHtmlContent RenderAction(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");
if (area == null)
throw new ArgumentNullException("area");
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 currentHttpContext = helper.ViewContext?.HttpContext;
var httpContextFactory = GetServiceOrFail<IHttpContextFactory>(currentHttpContext);
var actionInvokerFactory = GetServiceOrFail<IActionInvokerFactory>(currentHttpContext);
var actionSelector = GetServiceOrFail<IActionSelectorDecisionTreeProvider>(currentHttpContext);
// creating new action invocation context
var routeData = new RouteData();
var routeParams = new RouteValueDictionary(parameters ?? new { });
var routeValues = new RouteValueDictionary(new { area = area, controller = controller, action = action });
var newHttpContext = httpContextFactory.Create(currentHttpContext.Features);
newHttpContext.Response.Body = new MemoryStream();
foreach (var router in helper.ViewContext.RouteData.Routers)
routeData.PushState(router, null, null);
routeData.PushState(null, routeValues, null);
routeData.PushState(null, routeParams, null);
var actionDescriptor = actionSelector.DecisionTree.Select(routeValues).First();
var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
// invoke action and retreive the response body
var invoker = actionInvokerFactory.CreateInvoker(actionContext);
string content = null;
await invoker.InvokeAsync().ContinueWith(task => {
if (task.IsFaulted)
{
content = task.Exception.Message;
}
else if (task.IsCompleted)
{
newHttpContext.Response.Body.Position = 0;
using (var reader = new StreamReader(newHttpContext.Response.Body))
content = reader.ReadToEnd();
}
});
return new HtmlString(content);
}
private static TService GetServiceOrFail<TService>(HttpContext httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
var service = httpContext.RequestServices.GetService(typeof(TService));
if (service == null)
throw new InvalidOperationException($"Could not locate service: {nameof(TService)}");
return (TService)service;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用以下方法之一从视图中调用:
@Html.RenderAction("action", "controller", "area", new { id = 1})
@Html.RenderAction("action", "controller", new { id = 1})
@Html.RenderAction("action", new { id = 1})
Run Code Online (Sandbox Code Playgroud)
注意:
如果未提供,控制器名称和可选的区域名称将默认为ActionContext中的相应值.
@Html.Action 被 ViewComponents 取代。我不喜欢 ViewComponents 有多种原因。
但是我正在使用@Html.Action 的替代模式
首先,我在控制器上创建操作,该操作返回部分视图,其中包含我想要在页面中显示的内容
[HttpGet]
public async Task<IActionResult> GetFoo()
{
return PartialView("_Foo", new Foo());
}
Run Code Online (Sandbox Code Playgroud)
然后我将 div 放置在应加载 foo 视图的页面上,并在该页面的底部包含 IIFE。即下面的代码将加载 GetFoo 视图,然后将该 html 插入到 id 为 foo-view 的 div 中。
<div class="page">
<div id="foo-view" data-url="@Url.Action(action: "GetFoo", controller: "Home")"></div>
</div>
<script>
$(document).ready(function () {
(function () {
var url = $("#foo-view").data("url");
$("#foo-view").load(url);
})();
});
</script>
Run Code Online (Sandbox Code Playgroud)
您可能还想在从服务器获取视图时显示微调器。
我使用了这个页面上的人的代码来得到正确的结果。
例如,在旧类中,执行以下代码时,显示错误
@Html.RenderAction("About", "Home")
Run Code Online (Sandbox Code Playgroud)
以下代码已修复:
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Routing;
namespace Microsoft.AspNetCore.Mvc.Rendering
{
public static class HtmlHelperViewExtensions
{
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, object parameters = null)
{
var controller = (string)helper.ViewContext.RouteData.Values["controller"];
return RenderAction(helper, action, controller, parameters);
}
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, object parameters = null)
{
var area = (string)helper.ViewContext.RouteData.Values["area"];
return RenderAction(helper, action, controller, area, parameters);
}
public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
{
if (action == null)
throw new ArgumentNullException(nameof(controller));
if (controller == null)
throw new ArgumentNullException(nameof(action));
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 currentHttpContext = helper.ViewContext.HttpContext;
var httpContextFactory = GetServiceOrFail<IHttpContextFactory>(currentHttpContext);
var actionInvokerFactory = GetServiceOrFail<IActionInvokerFactory>(currentHttpContext);
var actionSelector = GetServiceOrFail<IActionDescriptorCollectionProvider>(currentHttpContext);
// creating new action invocation context
var routeData = new RouteData();
var routeParams = new RouteValueDictionary(parameters ?? new { });
var routeValues = new RouteValueDictionary(new { area, controller, action });
var newHttpContext = httpContextFactory.Create(currentHttpContext.Features);
newHttpContext.Response.Body = new MemoryStream();
foreach (var router in helper.ViewContext.RouteData.Routers)
routeData.PushState(router, null, null);
routeData.PushState(null, routeValues, null);
routeData.PushState(null, routeParams, null);
var actionDescriptor = actionSelector.ActionDescriptors.Items.First(i => i.RouteValues["Controller"] == controller && i.RouteValues["Action"] == action);
var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
// invoke action and retreive the response body
var invoker = actionInvokerFactory.CreateInvoker(actionContext);
string content = null;
await invoker.InvokeAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
content = task.Exception.Message;
}
else if (task.IsCompleted)
{
newHttpContext.Response.Body.Position = 0;
using (var reader = new StreamReader(newHttpContext.Response.Body))
content = reader.ReadToEnd();
}
});
return new HtmlString(content);
}
private static TService GetServiceOrFail<TService>(HttpContext httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
var service = httpContext.RequestServices.GetService(typeof(TService));
if (service == null)
throw new InvalidOperationException($"Could not locate service: {nameof(TService)}");
return (TService)service;
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下示例均已测试成功:
@Html.RenderAction("About")
@Html.RenderAction("About", "Home")
@Html.RenderAction("About", new { data1 = "test1", data2 = "test2" })
@Html.RenderAction("About", "Home", new { data1 = "test1", data2 = "test2" })
Run Code Online (Sandbox Code Playgroud)
对于网络核心 2.0
using Microsoft.AspNetCore.Mvc.Infrastructure;
Run Code Online (Sandbox Code Playgroud)
代替
// var actionSelector = GetServiceOrFail<IActionSelectorDecisionTreeProvider>(currentHttpContext);
var actionSelector = GetServiceOrFail<IActionDescriptorCollectionProvider>(currentHttpContext);
Run Code Online (Sandbox Code Playgroud)
和
// var actionDescriptor = actionSelector.DecisionTree.Select(routeValues).First();
var actionDescriptor = actionSelector.ActionDescriptors.Items.Where(i => i.RouteValues["Controller"] == controller && i.RouteValues["Action"] == action).First();
Run Code Online (Sandbox Code Playgroud)