从控制器返回新数据后刷新razor视图

从控制器返回新数据后刷新razor视图,razor,asp.net-core,asp.net-core-mvc,Razor,Asp.net Core,Asp.net Core Mvc,我有以下视图显示来自控制器的游戏相关数据 当页面最初加载时,它会点击一个索引控制器,该控制器只列出所有创建的游戏会话(总共100个) 但是,有一个输入字段,用户可以在其中输入日期,然后单击按钮 单击时,此按钮将日期和时间发送到另一个名为GamingSessionsByDate的方法 GamingSessionsByDate方法然后返回新数据,其中仅包含开始日期为用户输入日期的游戏会话 以下是视图: @model IEnumerable<GamingSessions.Session>

我有以下视图显示来自控制器的游戏相关数据

当页面最初加载时,它会点击一个索引控制器,该控制器只列出所有创建的游戏会话(总共100个)

但是,有一个输入字段,用户可以在其中输入日期,然后单击按钮

单击时,此按钮将日期和时间发送到另一个名为GamingSessionsByDate的方法

GamingSessionsByDate方法然后返回新数据,其中仅包含开始日期为用户输入日期的游戏会话

以下是视图:

@model IEnumerable<GamingSessions.Session>

@{
    ViewData["Title"] = "GamingSessionsByDate";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Gaming Sessions By Date</h2>

<input type="date" name="gameSession" id="gameSession">
<input type="Submit" id="postToController" name="postToController" Value="Find" />
@section Scripts
    {
    <script type="text/javascript">
        $("#postToController").click(function () {
            var url = '@Url.Action("GamingSessionsByDate", "GameSession")'; 
            var inputDate = new Date('2019-01-23T15:30').toISOString();
            $.ajax({
                type: "POST",
                url: url,
                data: "startdate=" + inputDate,
                success: function (data) {
                    console.log("data: ", data);
                }
            });
        });

    </script>
}

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.GameName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.PlayDuration)
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.GameName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.PlayDuration)
            </td>
        </tr>
        }
    </tbody>
</table>
顺便说一下,我已经在上面的AJAX调用中硬编码了一个日期时间值,我知道它包含5个游戏会话

请注意,我正在用AJAX成功方法写出从控制器返回的数据

因此,当我点击按钮时,屏幕上什么也没有发生,我只看到从调用索引控制器开始的最初加载的100个游戏会话

然而,在幕后,我可以看到我需要的5个游戏会话通过Ajax调用中的console.log命令写入控制台

在VisualStudio中逐步完成项目时,我也看到了正确的数据

因此,看起来一切正常,但视图/页面似乎没有刷新

那么,如何让数据显示在页面上呢


谢谢

JavaScript中的
XMLHttpRequest
对象(实际上发出“AJAX”请求)就是所谓的“瘦客户端”。您的web浏览器是一个“厚客户端”,它不仅仅是发出请求和接收响应:它实际上是自动执行一些操作,例如获取返回的HTML、CSS和JavaScript并“运行”它们,构建DOM并将漂亮的图片和文本呈现到您的屏幕上。相反,瘦客户机实际上只是发出请求并接收响应。就这样。它自己不做任何事情。作为开发人员,您有责任使用响应来实际执行某些操作

在这里的例子中,这意味着获取您收到的响应并操纵DOM,以使用检索到的不同游戏会话替换游戏会话列表。如何做到这一点取决于您从AJAX调用返回的响应。它可以是准备插入的HTML,也可以是JSON之类的对象。在前一种情况下,您实际上只是选择DOM中的某个父元素,然后用收到的响应替换其innerHTML。在后一种情况下,您需要使用JSON数据来实际构建元素并将其插入DOM

直接返回HTML更容易,但灵活性也较低。返回JSON给了您最大的自由度,但要操作DOM来显示该数据更为困难。这通常是您希望使用客户端框架(如Vue、Angular、React等)的地方。所有这些都可以创建模板化组件。这样,您只需更改底层数据源(即,将数据设置为返回的JSON),组件就会做出相应的反应,根据需要操纵DOM来创建视图

我个人喜欢使用Vue,因为它在开始使用Vue时摩擦最小,而且使用起来非常简单。例如:

<div id="App">

    <input type="date" v-model="startDate" />
    <button type="button" v-on:click="filterGameSessionsByDate">Find</button>

    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.GameName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.PlayDuration)
                </th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="item in items">
                <td>{{ item.GameName }}</td>
                <td>{{ item.PlayDuration }}</td>
            </tr>
        </tbody>
    </table>

</div>

如果你不太习惯JS,那可能看起来有点怪。我只是在这里使用所谓的闭包:就地定义和调用函数。它采用
options
param,该参数由底部的括号填充。在这些文件中,我创建了一个匿名对象,它保存了我需要的信息,比如要显示的初始项目和从中获取过滤结果的URL。然后,该对象被编码为JSON并转储到页面。

因为页面上没有表单。。。如果你在写一篇AJAX文章,你需要自己处理结果。您需要用返回的响应替换元素(
)的内容。你可以在这里看到一个类似的例子。如果你要返回整个页面,那么放弃AJAX,只做一个标准的表单帖子。一点也不。“现代”的方式,如果有这种情况的话,就是使用后端作为JSON返回存储库,完全构建客户端,使用Angular之类的框架来处理路由、视图等。然而,这更多地与流行的方式有关,而不是正确的甚至唯一的方式。服务器端应用程序仍然是完全有效和相关的。具体来说,您有一个服务器端应用程序,您正试图将其视为客户端应用程序。是的,绝对如此。然而,你也可以做一个混合应用,不是每个交互都涉及到服务器的往返,只是主要的交互,比如路由到新页面。在这种情况下,您可以使用与我在回答中发布的代码类似的代码,通过AJAX处理过滤后的游戏会话,但为此,您的端点需要返回JSON。如果您返回的是完整的HTML页面,则与此无关,而是在浏览器中更改整个页面,这是通过form post而不是JS完成的。如果您想构建客户端应用程序,则需要使用Angular之类的框架。ASP.NET核心仍然可以在后端使用,但您只需构建一个API(即,没有Razor页面)。如果你想使用Razor页面,那么你正在构建一个服务器端应用程序,或者可能是一个混合应用程序。对于前者,您需要决定哪些操作构成了完全更改浏览器页面,而不是将一点新数据拉到已经呈现的页面。您可以使用AJAX来执行诸如更新项目数量、删除项目等操作。但是,当您准备结帐时,您将完全切换到结帐页面。
<div id="App">

    <input type="date" v-model="startDate" />
    <button type="button" v-on:click="filterGameSessionsByDate">Find</button>

    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.GameName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.PlayDuration)
                </th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="item in items">
                <td>{{ item.GameName }}</td>
                <td>{{ item.PlayDuration }}</td>
            </tr>
        </tbody>
    </table>

</div>
(function (options) {
    let vm = new Vue({
        el: '#App",
        data: {
            items: options.items,
            startDate: null
        },
        methods: {
            filterGameSessionsByDate: function () {
                let self = this;
                $.ajax({
                    type: "POST",
                    url: options.filterByDateUrl,
                    data: "startdate=" + self.startDate,
                    success: function (data) {
                        self.items = data;
                    }
                });
            }
        }
    });
})(
    @Html.Raw(Json.Encode(new {
        items = Model,
        filterByDateUrl = Url.Action("GamingSessionsByDate", "GameSession")
    }))
 )