代码之家  ›  专栏  ›  技术社区  ›  SkyeBoniwell

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

  •  1
  • SkyeBoniwell  · 技术社区  · 5 年前

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

    当页面最初加载时,它会碰到一个索引控制器,该控制器只列出所有创建的游戏会话(总共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 回复  |  直到 5 年前
        1
  •  2
  •   Chris Pratt    5 年前

    这个 XMLHttpRequest javascript中的对象(实际上是“ajax”请求)就是所谓的“瘦客户机”。您的Web浏览器是一个“厚客户端”,它不仅仅是发出请求和接收响应:它实际上是自动执行一些操作,例如获取返回的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并转储到页面。