0

想象我们有一个控制器

1)一个动作开始一些长时间的操作,向会话中写入一些东西并立即呈现一些用户友好的消息:

    public ActionResult Search(string query)
    {
        _searchProvider.Ready += SearchResultReady;
        _searchProvider.Request(query);
        Session["query"] = query;
        return Results();
    }
    private void SearchResultReady(IEnumerable<IObject> results)
    {
        Session["searchResult"] = results.ToList();
    }

当“搜索”完成后,结果将被保存Session

我们这样做的原因是在结果准备好时显示结果(用 请求ajax

public ViewResult Results()
{
    if (Session["searchResult"] == null)
        return View("Wait");

    var query = Session["query"] as string;
    var list = Session["searchResult"] as IList<IObject>;
    var model = new ResultModel(query, list);
    return View("Results", model);
}

现在的问题是,在 Ready 事件上,它Session是 null

在请求之间保存控制器状态的正确方法是什么

4

1 回答 1

1

您将无法为此使用会话。会话不通过 AJAX 传输,因此您访问的 API 端点永远不会获得要查找的会话令牌。事实上,如果您正在处理一个真正的 REST API,那么一开始就没有会话之类的东西。HTTP 是一种无状态协议。

此外,如果您在控制器操作中执行任何操作,则在实际准备好结果之前不会返回响应,从而无需稍后使用 AJAX 获取它。即使您实现了异步(您甚至没有在这里执行),也只是将线程释放回服务器池,以便它可以处理其他请求,直到操作完成;它不会更快地返回响应。

如果您想先加载页面,然后从长时间运行的任务中获取数据,您应该简单地呈现页面并让 API 端点在页面通过 AJAX 触发对它的请求时完成工作。在其上实现异步,这样您就不会死锁线程,并在用户等待 AJAX 请求完成时向他们展示一些加载动画。

更新

控制器动作

public ActionResult Search(string query)
{
    return View();
    // that's right: do nothing here, just return the view
}

视图的 JavaScript

var interval;

$(document).ready(function () {
    var query = location.search.split('=')[1];
    $.post('/do/some/work', { query: query }, function (data) {
        // render data
        clearInterval(interval);
    });

    function checkStatus() {
        $.get('/check/on/status', function (data) {
            // data would contain percentage value or something,
            //use that to update progress bar
        });
    }

    interval = setInterval(checkStatus, 1000);
});

这一切都又快又脏。您应该找到一种更可靠的方法来获取搜索查询。甚至可以在您的操作中使用视图模型设置它,然后将其返回到您的视图或其他东西中。此外,JavaScript 应该使用正确的命名空间,这样其他一些脚本就不会在你的interval变量上运行,等等。

于 2013-10-22T16:17:33.007 回答