从 ASP.NET MVC 控制器向 ASP.NET web API 控制器发送数据时的待处理请求
Pending Requests When Posting Data to ASP.NET web API Controller from ASP.NET MVC Controller
我正在使用 ASP.NET MVC 和 ASP.NET WEB API 进行 SOA 项目。这两个项目都在不同的解决方案中,所以我们有一个 mvc 站点和一个 web api 站点,mvc 站点使用 http 方法操作调用 web api 站点。
考虑到那个场景,当我从我的 mvc 控制器 POSTING 一些数据到网络 API 时,我面临一个奇怪的行为。当我执行 GET 操作时,一切正常。这是我正在做的事情:
在我的 cshtml 视图中,我有一个 js 代码可以 ajax 调用我的 MVC 控制器:
>里面的JS代码Create.cshtml:
var create = (function () {
var _init = function (container, starter, url) {
$(starter).autocomplete({
minLength: 3,
focus: function () {
return false;
},
select: function (event, ui) {
var terms = this.value.replace(" ", "").split(',');
terms.pop();
terms.push(ui.item.label);
terms.push("");
this.value = terms.join(",");
return false;
},
search: function (event, ui) {
if (_extractLast(this.value).length < 3)
return false;
return true;
},
source: function (request, response) {
_execute(request, response, url);
}
});
};
var _extractLast = function (term) {
var termArray = term.split(',');
var lastTerm = termArray[termArray.length - 1];
return lastTerm.replace(' ', '');
};
var _execute = function (request, response, url) {
var responseCallback = response;
$.ajax({
url: '\Comunication\Contacts',
async: true,
type: 'POST',
dataType: 'json',
data: { termo: _extractLast(request.term) },
success: function (data) {
responseCallback($.map(data, function (item) {
return { label: item.Name, value: item.Id }
}));
}
});
}
return { init: _init };})();
我从我的控制器内部调用一个来自专门服务层的方法来对我的 WEB API SITE 执行 SOA 操作的 POST 请求,如下所示:
> MVC 控制器代码:
public class ComunicationController : BaseController{
[HttpPost]
public async Task<JsonResult> Contacts(string termo)
{
var contacts = new ContactServices.ConsumeAsync(new ContactParameter{Term: termo});
return Json(contacts, JsonRequestBehavior.AllowGet);
}
}
> 图层服务代码:
public class ContactServices{
public async Task<List<ContactsDTO>> ConsumeAsync(ContactParameter parameter)
{
using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient())
{
httpClient.BaseAddress = new Uri("http://localhost:123456/api/comunication/contacts");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await httpClient.PostAsJsonAsync(new Uri("http://localhost:123456/api/comunication/contacts"), parameter);
return JsonConvert.DeserializeObjectAsync<ResponseProxy<List<ContactsDTO>>>(response.Content.ReadAsStringAsync().Result).Result.data;
}
}
}
My WEB API SITE 接受请求,按预期处理请求,这里不用担心。但是当我 return 从我的 WEB API CONTROLLER 到 MVC 站点的 HttpResponseMessage 在 POST 操作下,根据我的网络监视器,请求响应永远挂在挂起状态....
所以基本上我的请求挂起,协议状态为待定,我从未收到请求响应,这是一张照片:
Pending Status from My Post Request
正如我所说,当我向我的网络 api 发出 GET 请求时,一切正常,但是当我向 POST 发出请求时,这种情况发生了...
你的问题出在这一行:
return JsonConvert.DeserializeObjectAsync<ResponseProxy<List<ContactsDTO>>>(response.Content.ReadAsStringAsync().Result).Result.data;
使用任务的 Result
属性 会在 MVC 控制器上产生死锁。如果 API 是异步的,那么总是 await
任务。
var content = await response.Content.ReadAsStringAsync();
var deserialized = await JsonConvert.DeserializeObjectAsync<ResponseProxy<List<ContactsDTO>>>(content);
return deserialized.data;
要了解更多关于为什么你不应该阻塞异步方法,请查看这个很棒的post:
Don't Block on Async Code
我正在使用 ASP.NET MVC 和 ASP.NET WEB API 进行 SOA 项目。这两个项目都在不同的解决方案中,所以我们有一个 mvc 站点和一个 web api 站点,mvc 站点使用 http 方法操作调用 web api 站点。
考虑到那个场景,当我从我的 mvc 控制器 POSTING 一些数据到网络 API 时,我面临一个奇怪的行为。当我执行 GET 操作时,一切正常。这是我正在做的事情:
在我的 cshtml 视图中,我有一个 js 代码可以 ajax 调用我的 MVC 控制器:
>里面的JS代码Create.cshtml:
var create = (function () {
var _init = function (container, starter, url) {
$(starter).autocomplete({
minLength: 3,
focus: function () {
return false;
},
select: function (event, ui) {
var terms = this.value.replace(" ", "").split(',');
terms.pop();
terms.push(ui.item.label);
terms.push("");
this.value = terms.join(",");
return false;
},
search: function (event, ui) {
if (_extractLast(this.value).length < 3)
return false;
return true;
},
source: function (request, response) {
_execute(request, response, url);
}
});
};
var _extractLast = function (term) {
var termArray = term.split(',');
var lastTerm = termArray[termArray.length - 1];
return lastTerm.replace(' ', '');
};
var _execute = function (request, response, url) {
var responseCallback = response;
$.ajax({
url: '\Comunication\Contacts',
async: true,
type: 'POST',
dataType: 'json',
data: { termo: _extractLast(request.term) },
success: function (data) {
responseCallback($.map(data, function (item) {
return { label: item.Name, value: item.Id }
}));
}
});
}
return { init: _init };})();
我从我的控制器内部调用一个来自专门服务层的方法来对我的 WEB API SITE 执行 SOA 操作的 POST 请求,如下所示:
> MVC 控制器代码:
public class ComunicationController : BaseController{
[HttpPost]
public async Task<JsonResult> Contacts(string termo)
{
var contacts = new ContactServices.ConsumeAsync(new ContactParameter{Term: termo});
return Json(contacts, JsonRequestBehavior.AllowGet);
}
}
> 图层服务代码:
public class ContactServices{
public async Task<List<ContactsDTO>> ConsumeAsync(ContactParameter parameter)
{
using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient())
{
httpClient.BaseAddress = new Uri("http://localhost:123456/api/comunication/contacts");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await httpClient.PostAsJsonAsync(new Uri("http://localhost:123456/api/comunication/contacts"), parameter);
return JsonConvert.DeserializeObjectAsync<ResponseProxy<List<ContactsDTO>>>(response.Content.ReadAsStringAsync().Result).Result.data;
}
}
}
My WEB API SITE 接受请求,按预期处理请求,这里不用担心。但是当我 return 从我的 WEB API CONTROLLER 到 MVC 站点的 HttpResponseMessage 在 POST 操作下,根据我的网络监视器,请求响应永远挂在挂起状态....
所以基本上我的请求挂起,协议状态为待定,我从未收到请求响应,这是一张照片: Pending Status from My Post Request 正如我所说,当我向我的网络 api 发出 GET 请求时,一切正常,但是当我向 POST 发出请求时,这种情况发生了...
你的问题出在这一行:
return JsonConvert.DeserializeObjectAsync<ResponseProxy<List<ContactsDTO>>>(response.Content.ReadAsStringAsync().Result).Result.data;
使用任务的 Result
属性 会在 MVC 控制器上产生死锁。如果 API 是异步的,那么总是 await
任务。
var content = await response.Content.ReadAsStringAsync();
var deserialized = await JsonConvert.DeserializeObjectAsync<ResponseProxy<List<ContactsDTO>>>(content);
return deserialized.data;
要了解更多关于为什么你不应该阻塞异步方法,请查看这个很棒的post:
Don't Block on Async Code