我有一个Web API控制器定义如下:
[HttpPost]
public class EmailActivitiesController : ApiController
{
public HttpResponseMessage EmailAClientWithNewMailMessage(FormDataCollection aFormData)
{
}
}
使用以下jQuery调用:
var aFormData = {};
$.support.cors = true;
$.ajax({
cache: false,
url: '/api/EmailActivities/EmailAClientWithNewMailMessage',
type: "POST",
dataType: "json",
data: aFormData,
success: function (callback) {
//Platform.LoadingPanelHide();
alert("Successfully sent the email.");
},
error: function (data) {
var errorObject = JSON.parse(data);
//Platform.LoadingPanelHide();
alert('There was a problem sending the email message to the individual selected.\n\n' + errorObject.responseText.message);
}
});
并且所有工作和API方法都已达成。但是,只要我填充aFormData如下:
var aFormData = {};
aFormData['aMessageInfo'] = "test";
//And sending via form data
$.support.cors = true;
$.ajax({
cache: false,
url: '/api/EmailActivities/EmailAClientWithNewMailMessage',
type: "POST",
dataType: "json",
data: aFormData,
success: function (callback) {
//Platform.LoadingPanelHide();
alert("Successfully sent the email.");
},
error: function (data) {
var errorObject = JSON.parse(data);
//Platform.LoadingPanelHide();
alert('There was a problem sending the email message to the individual selected.\n\n' + errorObject.responseText.message);
}
});
然后没有达到该方法,我接受了一个带有以下JSON响应的HttpResonseCode.OK:
{
"result": null,
"success": false,
"error": {
"code": 0,
"message": "An internal error occured during your request!",
"details": null,
"validationErrors": null
},
"unAuthorizedRequest": false
}
对于我的生活,我无法弄清楚为什么会这样。有没有人有任何见解。
更新
这是POST请求。
异常日志:
ERROR 2015-01-29 15:51:08,250 [17 ] Default - Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.
System.Web.Http.HttpResponseException: Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.
at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger)
at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()
更新#2
我现在已经采用了如下建议的使用DTO的方法:
var aMessageInfo = {
subject: Base64.encode($("#txtSendEmailSubject").val()),
body: Base64.encode($("#txtSendEmailBody").val())
};
$.support.cors = true;
$.ajax({
cache: false,
url: '/api/EmailActivities/Dono2',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(aMessageInfo),
success: function (callback) {
//Platform.LoadingPanelHide();
alert("Successfully sent the email.");
},
error: function (data) {
var errorObject = JSON.parse(data);
//Platform.LoadingPanelHide();
alert('There was a problem sending the email message to the individual selected.\n\n' + errorObject.responseText.message);
}
});
然后在WebAPI中它可以工作,如果我只有:
public class EmailActivitiesController : ApiController
{
[HttpPost]
public HttpResponseMessage Dono2(MessageInfo aMessageInfo)
{
}
}
但是,只要我还有 EmailAClientWithNewMailMessage 作为方法:
public class EmailActivitiesController : ApiController
{
[HttpPost]
public HttpResponseMessage Dono2(MessageInfo aMessageInfo)
{
}
[HttpPost]
public HttpResponseMessage EmailAClientWithNewMailMessage(FormDataCollection aFormData)
{
}
我收到错误:
{
"message":"An error has occurred.",
"exceptionMessage":"Multiple actions were found that match the request: \r\nDono2 on type MakersLane.WebApi.Controllers.EmailActivitiesController\r\nEmailAClientWithNewMailMessage on type MakersLane.WebApi.Controllers.EmailActivitiesController",
"exceptionType":"System.InvalidOperationException",
"stackTrace":" at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n at Abp.WebApi.Controllers.Dynamic.Selectors.AbpApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
现在虽然控制器Dono2和EmailClientWithNewMessage上有两个动作,但我不明白为什么它们不能被分开,因为它们显然有不同的名称,虽然它们都有一个参数,但它们的名称不同,并且属于不同类型。
任何人都可以解释为什么会这样吗?
答案 0 :(得分:2)
我不在Windows机器上,因此现在无法测试此写入,但我将在下面提供替代解决方案。从POST中发送的查询字符串到FormDataCollection
的映射存在问题,并且我认为它可以通过使用这样的JSON对象来解决:
{ aFormData : { aMessageInfo : "test" } }
但我无法证实。我相信以下解决方案会更好,所以除非必须使用FormDataCollection,否则请使用它。
我建议使用视图模型而不是FormDataCollection
,因为值的映射变得乏味:
public class Message
{
public string Client { get; set; }
public string Content { get; set; }
}
然后将您的控制器更改为:
public HttpResponseMessage EmailAClientWithNewMailMessage(Message data)
{
// use the deserialised object here
return data.Client;
}
你的jquery看起来像这样(注意添加了content-type参数和JSON.stringify调用):
var aFormData = {};
aFormData['aMessageInfo'] = "test";
//And sending via form data
$.support.cors = true;
$.ajax({
cache: false,
url: '/api/EmailActivities/EmailAClientWithNewMailMessage',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(aFormData),
success: function (callback) {
//Platform.LoadingPanelHide();
alert("Successfully sent the email.");
},
error: function (data) {
var errorObject = JSON.parse(data);
//Platform.LoadingPanelHide();
alert('There was a problem sending the email message to the individual selected.\n\n' + errorObject.responseText.message);
}
});
答案 1 :(得分:1)
我认为这段代码覆盖了结果。
try
{
if (task.Result == null)
{
return new AjaxResponse();
}
if (task.Result is AjaxResponse)
{
return task.Result;
}
return new AjaxResponse(task.Result);
}
答案 2 :(得分:1)
你看过Logs / logs.txt文件了吗?它会抛出异常。
干杯 杰夫
答案 3 :(得分:1)
我觉得乔尔是对的。我有问题作为参数传递字符串,因此将我的所有输入包装在DTO对象中,它工作正常。
干杯 杰夫
答案 4 :(得分:0)
问题是:ABP系统配置为仅使用JSON数据。当您更改这样的代码时,它可以工作:
$.ajax({
cache: false,
url: '/api/EmailActivities/EmailAClientWithNewMailMessage',
type: "POST",
contentType: 'application/json',
dataType: "json",
data: JSON.stringify({ aMessageInfo: 'test' }),
success: function (callback) {
//Platform.LoadingPanelHide();
alert("Successfully sent the email.");
},
error: function (data) {
var errorObject = JSON.parse(data);
//Platform.LoadingPanelHide();
alert('There was a problem sending the email message to the individual selected.\n\n' + errorObject.responseText.message);
}
});
我添加了contentType。以这种方式调用方法,但是表单数据不会出现在方法中。也许FormDataCollection不喜欢JSON帖子。
为什么你不使用简单的DTO类而不是FormDataCollection?这对于ABP项目来说更为自然。
在AbpWebApiModule中,它清除所有格式化程序并添加JSON和纯文本。
private static void InitializeFormatters()
{
GlobalConfiguration.Configuration.Formatters.Clear();
var formatter = new JsonMediaTypeFormatter();
formatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
GlobalConfiguration.Configuration.Formatters.Add(formatter);
GlobalConfiguration.Configuration.Formatters.Add(new PlainTextFormatter());
}
也许您可以使用GlobalConfiguration.Configuration.Formatters.Add添加其他格式化程序。
我是如何找到问题的? ABP定义了一个处理异常的事件(从v0.3.2开始):
这可以帮助您找到错误。
EventBus.Default.Register<AbpHandledExceptionData>(
data =>
{
//use data.Exception to see exception details
});