Skip to main content
 首页 » 编程设计

c#之WebAPI 中未达到带有 FormData 的 HTTP Post

2024年02月01日25emanlee

我有一个 Web API Controller 定义如下:

[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); 
        } 
    }); 

然后该方法未到达,我收到了一个 HttpResonseCode.OK 和以下 JSON 响应:

{ 
"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()" 
} 

现在虽然在 Controller Dono2 和 EmailClientWithNewMessage 上有两个 Action ,但我不明白为什么不能区分它们,因为它们显然具有不同的名称,尽管它们都有一个参数,但它们的名称和类型不同。

谁能解释为什么会这样?

请您参考如下方法:

我不在 Windows 机器上,所以现在无法测试此写入,但我将在下面提供替代解决方案。从 POST 中发送的查询字符串到 FormDataCollection 的映射存在问题,我认为可以通过使用像这样的 JSON 对象来解决它:

{ aFormData : { aMessageInfo : "test"} }

但我无法确认。我相信以下解决方案更好,所以除非您必须使用 FormDataCollection,否则请使用它。

我建议使用 View 模型而不是 FormDataCollection,因为值的映射变得乏味:

public class Message 
{ 
    public string Client { get; set; } 
    public string Content { get; set; } 
} 

然后将您的 Controller 更改为:

public HttpResponseMessage EmailAClientWithNewMailMessage(Message data) 
{ 
    // use the deserialised object here 
    return data.Client; 
} 

你的 jquery 看起来像这样(注意添加了内容类型参数和 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); 
    } 
});