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

时间:2019-01-23 17:36:51

标签: razor asp.net-core asp.net-core-mvc

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

页面最初加载时,它会到达一个索引控制器,该控制器仅列出曾经创建的所有游戏会话(共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>

以下是按日期返回游戏会话的控制器:

public IActionResult GamingSessionsByDate(DateTime startdate)
{

    var response = GetGameSessionsList(startdate);

    var r = response.Results;

    return View(r);
}

顺便说一句,我已经将日期时间值硬编码到上面的AJAX调用中,我知道它包含5个游戏会话。

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

因此,当我单击该按钮时,屏幕上什么都没有发生,我只看到最初从呼叫到索引控制器的100个游戏会话。

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

在Visual Studio中逐步浏览项目时,我还会看到正确的数据。

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

那么,如何获取该数据以显示在页面上?

谢谢!

1 个答案:

答案 0 :(得分:2)

JavaScript中的XMLHttpRequest对象(实际上发出“ AJAX”请求)就是所谓的“瘦客户端”。您的网络浏览器是一个“厚客户端”,它不仅执行请求并接收响应:它实际上会自动执行诸如返回的HTML,CSS和JavaScript之类的事情,并“运行”它们,构建DOM并渲染漂亮的图片。并在屏幕上显示文字。相反,瘦客户端实际上只是发出请求并接收响应。而已。它本身不会做任何事情。作为开发人员,您有责任使用响应来实际执行操作。

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

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

我个人喜欢使用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进行连接:

(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")
    }))
 )

如果您不习惯使用JS,那可能看起来有点时髦。我在这里仅使用所谓的闭包:就地定义和调用函数。它需要一个options参数,该参数由底部的括号填充。在这些内部,我正在创建一个匿名对象,其中包含我需要的信息,例如要显示的初始项以及要从中获得过滤结果的URL。然后,将该对象编码为JSON并转储到页面中。