ASP.NET Core中类似于Html.RenderAction的替代方法

45

我正在尝试从我的小型ASP.NET MVC 4应用程序切换到ASP.NET Core。

在我的MVC 4应用程序中,我有一个使用RenderSection的Layout文件:

@RenderSection("xyz", required: false)

然后,在我的索引文件中,我有:

@section xyz{
        @{Html.RenderAction("abc");}
    }

因此,我从Index中调用控制器操作方法abc()。abc()方法传递一个模型对象,并返回带有该模型的部分视图。

由于需要传递模型,因此我不能使用RenderPartial。

现在,在ASP.NET Core中,我没有RenderAction()方法。

我的问题是:如何从Index文件中调用控制器操作方法?是否有其他HTML帮助程序可用(尽管我没有看到任何)?

.


5
在ASP.NET Core中,@Html.Action(我知道你谈论的是RenderAction,但我相信它遵循了相同的概念)已被ViewComponents取代。参考:http://stackoverflow.com/questions/40341386/net-core-putting-views-into-a-tabs/40342752#40342752。祝好。 - dime2lo
谢谢提供链接。我正在尝试实现ViewComponents,看看它是否适用于我的项目。 - user6542823
看起来很痛苦。也没有ConfigurationManager。为了一个小应用程序需要阅读很多内容。这是否可以称为“与ASP.NET Core没有向后兼容性”? - user6542823
ASP.NET Core是一次重写,大多数但不是全部的概念都被保留了下来。比ViewComponents更简单的方法是使用Partial View。但如果需要逻辑或与主视图不同的模型,就像控制器操作所处理的那样,那么ViewComponent就是要使用的东西。 - Joe Audette
1
请问您能否分享控制器代码? - Karthic G
3个回答

40

我最终通过ViewComponent实现了它。所以,我用ViewComponent代替RenderAction():

@section xyz{
        @await Component.InvokeAsync("abc")
    }

其中abc是一个名为abcViewComponent的类。该ViewComponent如下所示:

public class abcViewComponent : ViewComponent
    {
        private DbContextOptions<MyContext> db = new DbContextOptions<MyContext>();
        public async Task<IViewComponentResult> InvokeAsync()
        {
            MyContext context = new MyContext(db);
            IEnumerable<tableRowClass> mc = await context.tableRows.ToListAsync();
            return View(mc);
        }
    }

然后,我在新文件夹“abc”下创建了一个视图,路径为Views/Home/Components/abc/Default.cshtml。

需要注意的是,视图名称为Default.cshtml,这就是它的工作方式。如果有更好的解决方案,请告诉我。

感谢您指引我使用ViewComponent。


4
我知道这样很苛刻,但是在C#中,类名应以大写字母开头,所以您的视图组件类应该是AbcViewComponent,表格行类应该是TableRowClass,以及context.tableRows 应改为 context.TableRows。否则,很高兴你已经让它工作了。 - akousmata
1
谢谢。我在我的项目中按照您所说的方式使用了大写字母开头的名称。这里只是举例小写字母。我会记住在以后发布时注意这一点。 - user6542823
4
值得注意的是,对于 ASP.NET Core 1.1 及更高版本,您可以通过标签助手调用视图组件: <vc:abc /> (来源:https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components) - MFry

10

仅用于补充上述问题,更安全的方法可能是像下面所示那样传递ViewComponent类的名称:

@section xyz{
    @await Component.InvokeAsync(nameof(yournamespace.abc))
}

尽管通常使用“默认视图”作为结果视图,但如果与默认不同,您也可以返回视图名称:

public class abcViewComponent : ViewComponent
{
    private DbContextOptions<MyContext> db = new DbContextOptions<MyContext>();
    public async Task<IViewComponentResult> InvokeAsync()
    {
        MyContext context = new MyContext(db);
        IEnumerable<tableRowClass> mc = await context.tableRows.ToListAsync();
        return View("YourViewName", mc);
    }
}

8

有一个解决方法,您可以使用Url.Action + JQuery来呈现内容。

您要呈现动作的视图将如下所示:

<div id="dynamicContentContainer"></div>
<script>   
    $.get('@Url.Action("GetData", "Home")', {id : 1}, function(content){
            $("#dynamicContentContainer").html(content);
        });
</script>

Home控制器:

[HttpGet]
public IActionResult GetData(int id)
{
   return PartialView(id);
}

这是一个视图

@model int 
<span>Values from controler :</span> @Model

如果您想要对请求获得更多的控制,您可以在这里阅读更多信息:jQuery.get()

14
这不等同于RenderAction,而是一种完全不同的方法。 - Paul Knopf
@PaulKnopf 除了缺乏 [ChildActionOnly] 支持之外,还有什么其他具体的不同之处吗? - Mars
1
这是MVC现在走向的糟糕之一。 <partial name="_PartialView" model="Model.object" /> 是可以的,但是 <render controller="Controller" action="Action" params=new { id : 'xyz' } /> 不行。 - darksider474
3
这种方法会在页面加载完成之后再呈现操作结果,而不是在加载期间。它需要 JavaScript 支持,在大多数桌面浏览器上可能不是问题,但对于移动设备来说可能会有挑战,尤其是在低速或不稳定的网络连接下,以及在使用较差的手机和奇特浏览器时。 - Sergey Kudriavtsev
@SergeyKudriavtsev 是的,正如我所说,这只是一个解决办法,但是是的,它在页面加载后运行。 - Kabindas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接