【发布时间】:2015-07-17 07:08:33
【问题描述】:
我在 .Net 上使用 MVC 5,我的用户流程如下所示:
- 用户在表单中输入地址。
- 使用 AJAX 将表单发布到控制器。
- 控制器将地址记录到数据库中。
- 控制器向 Bing 地图发出 WebClient 请求,以将地址地理编码为纬度和经度。
- 控制器将经纬度记录到数据库中。
- 控制器返回一个 AJAX 结果,该结果在客户端呈现到带有地址和纬度/经度的更新视图中。
我知道对 Bing 地图的调用应该在异步上下文中进行,以便我的网站的速度与 Bing 地图的速度分离。
相反,我认为我的流程应该是这样的:
- 用户在表单中输入地址。
- 使用 AJAX 将表单发布到控制器。
- 控制器将地址记录到数据库中。
- 控制器启动异步任务来进行地理编码和更新数据库
- 控制器向客户端返回一个显示更新地址的 AJAX 结果,并告诉它轮询客户端以完成地理编码结果。
我被困在第 4 步。这是我所拥有的:
public ActionResult GetLocation(int id)
{
Listing li = db.Listings.Find(id);
Task.Run(() => {
// update geocode if necessary
if (li.BizAddress.GeoStatus != BusinessAddress.GeocodeStatus.UpToDate &&
DateTime.Now - li.BizAddress.LastGeoAttempt > TimeSpan.FromHours(1))
{
Geocoder geo = new Geocoder();
GeocodeResult gr = geo.Geocode(li.BizAddress).Result;
if (gr.BadResult != true)
{
li.BizAddress.Latitude = gr.Location.Latitude;
li.BizAddress.Longitude = gr.Location.Longitude;
li.BizAddress.GeoStatus = BusinessAddress.GeocodeStatus.UpToDate;
}
else
{
// failed
li.BizAddress.Latitude = 0;
li.BizAddress.Longitude = 0;
li.BizAddress.GeoStatus = BusinessAddress.GeocodeStatus.BadResult;
}
li.BizAddress.LastGeoAttempt = DateTime.Now;
db.SaveChanges();
}
});
return PartialView("~/Views/Listing/ListingPartials/_Location.cshtml", li);
}
但是,当我到达 db.SaveChanges() 时,我得到一个异常,即 db 上下文已被释放。
我希望我的任务在闭包内运行异步,这样 db 仍然是一个有效的未处理变量。
这可能吗?我是异步编程的新手,我还不知道所有的习语。
附加信息:我在我的视图中呈现我的面板,如下所示:
@{Html.Action("GetLocation", new { id = Model.ID });}
我想保留这种行为,因为使用 AJAX 加载它可能会损害 SEO。
【问题讨论】:
-
不确定我是否完全理解,但在 #5 中的 IINM 在你想要做的事情中(投票),那仍然是 client-side 以便“打破”你的最后一个声明(使用 AJAX 加载会损害 SEO)(?) - 除了 Bing 调用(无论如何)之外,您的“其他内容”将被“完成”(渲染)。我不是大师,所以对于异常部分,您正在从 ASP.net 请求上下文中触发一个单独的任务(它是自己的上下文) - 所以它不是“线性的” - ASP.Net 请求上下文之前是“完成的”你的
Task(这就是为什么在下面的答案中使用async/await)
标签: c# asp.net-mvc asynchronous