How to return Json object to view in a Async method
function getSomeData() {
$.post(G开发者_如何学运维etTablesDataUrl, null,
function (data) {
alert(data);
});
}
here is then called a method in my HomeController.cs
public void GetTablesData()
{
WebClient webClinet = new WebClient();
webClinet.DownloadDataAsync( new Uri("http://somer_url"));
webClinet.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webClinet_DownloadDataCompleted);
}
when download is completed, next method is executed
void webClinet_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
byte[] responseArray = e.Result;
string s = responseArray.ToString();
ReturnDataToPage(s); // return json object
}
inside is am method to return data back to my page like this
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult ReturnDataToPage(string s)
{
var data = s;
return Json(data);
}
but I always get an empty string. What am I doing wrong???
You have two possibilities:
Use a normal controller and because the AJAX call is already async you probably wouldn't need more:
public class TablesController : Controller { [HttpPost] public ActionResult ReturnTables(string s) { using (var client = new WebClient()) { string result = client.DownloadString("http://example.com"); // Assuming the remote address returns a JSON object // if not parse the response and return Json return Content(result, "application/json"); } } }
Use an async controller and IOCP (I/O Completion Ports):
public class TablesController : AsyncController { [HttpPost] public void ReturnTablesAsync(string s) { AsyncManager.OutstandingOperations.Increment(); var client = new WebClient(); client.DownloadStringCompleted += (sender, e) => { try { AsyncManager.Parameters["result"] = e.Result; } finally { AsyncManager.OutstandingOperations.Decrement(); } }; client.DownloadStringAsync(new Uri("http://www.example.com")); } public ActionResult ReturnTablesCompleted(string result) { // Assuming the remote address returns a JSON object // if not parse the response and return Json return Content(result, "application/json"); } }
In both cases you would consume those actions the same way:
// Not sure exactly what was the purpose of the "s" query string
// parameter as I am not using it in the action
var data = { s: 'some data' };
$.post('<%= Url.Action("ReturnTables", "Tables") %>', data, function(result) {
// Do something with the result
});
The difference between those two approaches is that the async version would use I/O Completion Ports and wouldn't block any worker threads during the retrieval of the remote resource.
The main issue with your approach is that you are calling the external site ("http://somer_url") asynchronously.
This means that the action called by 'someDataDataUrl' (Which, I assume, is not shown in your question) will return immediately, and this is probably before the asynch call returns with your actual data.
The secondary issue (If my understanding of your - possibly mistyped - question is correct) is that when the asynch call handler is invoked, it calls 'ReturnDataToPage' (Should this be 'ReturnTables'?), and then does nothing with the JsonResult that it gets.
You would be better off calling the external site Synchronously (although this introduces block issues, so timeouts need to be introduced) and the returning the result of this call correctly.
Doing this, however, would entail a bit of extra research (Not something that I've done from .NET, I'm afraid)
精彩评论