在 MVC 中将事件移交给会话 ASP.NET

本文关键字:会话 ASP NET MVC 事件 | 更新日期: 2023-09-27 18:36:22

Imaing我们有一个控制器

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为空

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

在 MVC 中将事件移交给会话 ASP.NET

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

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

如果要先加载页面,然后从长时间运行的任务中获取数据,则只需呈现页面,并在页面通过 AJAX 触发请求后让 API 终结点执行工作。在此基础上实现异步,这样就不会使线程死锁,并在用户等待 AJAX 请求完成时向用户呈现一些加载动画。

更新

控制器操作

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

JavaScript for View

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 变量上运行,等等。