【问题标题】:Why cannot I send a post to my WebApi through AngularJS's POST?为什么我不能通过 AngularJS POST 向我的 Web Api 发送帖子?
【发布时间】:2017-03-19 15:01:07
【问题描述】:

我已经将“mytest.html”发送到 IIS,这个项目是由 WebApi+Angularjs 组成的,我的 webApi 无法获得正确的请求……我不知道为什么?

【HTML代码】

<!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
    <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
    </head>

    <body>
       <div ng-app="A" ng-controller="Test">
           <form method='post' name='myForm'>
               <table width="100%">
                  <tr>
                      <td>Name:</td>
                      <td><input type='text' ng-model='user.name' name='myname' required/>
                               <span style='color:red' ng-show='myForm.myname.$dirty && myForm.myname.$invalid'>Name cannot be empty!</span>
                      </td>
                 </tr>

                  <tr>
                      <td>Gender:</td>
                      <td>
                        <div ng-repeat='s in sexs'>
                        <input type='radio' ng-model='user.sex' name='mysex' value='{{s}}'>
                        {{s}}
                        </div>
                      </td>
                 </tr>
                 <tr>
                       <td>Hobby:</td>
                       <td>
                       <select ng-model='user.love' name='selLove'>
                           <option ng-repeat='l in loves' value='{{l}}'>{{l}}</option>
                       </select>
                       <span style='color:red' ng-show='selChoice(myForm.selLove.$dirty);'>You cannot choose "Please choose"</span>
                        </td>
                 </tr>
             </table>
             <input type ='submit' value='Submit' ng-click='isDisable();'/>
           </form>
      </div>

    <script>

         var app = angular.module('A',[],function($httpProvider){

            $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
         });


         app.controller('Test',function($scope,$http){

           $scope.user = {};

           $scope.sexs = ['M','F'];
           $scope.loves = ['Please choose','Programming','Piano','Swimming'];

           $scope.user.sex = 'M';
           $scope.user.love = 'Please choose';

           $scope.selChoice= function(isDirty){
                var isFalse = (myForm.selLove.value == 'Please choose' && isDirty);
                $scope.myForm.selLove.$invalid = isFalse;
                $scope.myForm.$invalid |= isFalse;
                return isFalse;
           };

           $scope.isDisable = function(){

                $scope.selChoice(true);

                var requestData = $.param($scope.user);
                alert(requestData);

                if($scope.myForm.$invalid){
                    alert('Invalid form');
                }
                else{
                    $http({
                        method:'POST',
                        data: requestData,
                        url:'http://localhost:60031/api',
                        success: function (data){
                            alert(JSON.stringify(data));
                        }
                    });
                }
           };
         });
    </script>

      </body>
    </html>

【WebApi代码】

 namespace AngularJSDemo.Controllers
    {
        using Models;
        using System.Web.Http;

        public class DefaultController : ApiController
        {
            [HttpPost]
            public Person GetPerson([FromBody] Person p)
            {
                return p;
            }
        }
    }

【型号代码】

 namespace AngularJSDemo.Models
    {
        public class Person
        {
            public string Name { get; set; }
            public string Sex { get; set; }
            public string Love { get; set; }
        }
    }

【注册码】

namespace AngularJSDemo
{
    using Newtonsoft.Json.Serialization;
    using System.Net.Http.Formatting;
    using System.Web.Http;

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Formatters.Clear();

            var jsonFormatInstance = new JsonMediaTypeFormatter();
            jsonFormatInstance.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            config.Formatters.Add(jsonFormatInstance);

            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional,controller="Default" }
            );

        }
    }
}

请注意,我的谷歌浏览器控制台中的错误是:

angular.js:10695 POST http://localhost:60031/api 415(不支持的媒体类型)


我也尝试过使用json,但没有帮助:(

$http({
                    method:'POST',
                    data: {p:$scope.user},
                    url:'http://localhost:60031/api/Default',
                    success: function (data){
                        alert(JSON.stringify(data));
                    }
                });

我的 Content-Type 是:

var app = angular.module('A',[],function($httpProvider){

                $httpProvider.defaults.headers.post['Content-Type'] = 'application/json';
             });

因为我有不同种类的端口,为了跨域,我也这样做了:

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="*" />
        <add name="Access-Control-Request-Methods" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

【问题讨论】:

  • @Mikkel:抱歉还是没有帮助
  • 这应该是由于内容类型标头设置不正确。你是怎么测试的?你能更新一下问题吗?
  • 不需要使用jQuery来序列化对象。 AngularJS $http 服务自动使用内置的序列化程序。使用$.param 对其进行序列化可能会导致 415 错误。
  • @SamiKuhmonen:我已经注册了application/json或者application/url-form……,但是没有任何帮助。

标签: javascript angularjs asp.net-mvc asp.net-web-api


【解决方案1】:

网址错误

网址应该是:http://localhost:60031/api/Default

$http({
                        method:'POST',
                        data: requestData,
                        url:'http://localhost:60031/api/Default',
                        success: function (data){
                            alert(JSON.stringify(data));
                        }
                    });

另外,最好将数据提交为 JSON 而不是 form-urlencoded

【讨论】:

  • 没有。你的还是帮不了我……而且,我已经在 C# 的注册中设置了默认控制器。我想知道为什么我要把它改成“application/json”?你看我把我的函数的输入参数标记为[FromBody]——来自form而不是“json”格式。 “JSON”正是我所写的。
  • 您正在构建一个 REST 服务,通常以 JSON 格式共享数据,而不是 FORM 字段您可以共享发送到服务的请求正文吗?对于您使用 json 的尝试,它应该是 data:{p:$scope.user}
  • 嗯……还是一点帮助都没有:(你说的{p:……}是什么意思)?
  • @DongWei 我想在这里帮助您,{p:...} 是将发送到 Web API 的 JSON 对象,您的操作有一个 Person 类型的参数被称为p,您需要发送一个具有相同名称的 JSON 对象,这就是 Web API 将如何理解将请求正文绑定到您的操作参数。另外,请检查发送的请求并共享数据以了解正在发送到服务器的内容
  • 我怀疑我的“跨域”是否有问题?我在 web.config 中更新了我的代码
【解决方案2】:

总而言之,我认为:

1) 我们确实必须使用默认值并将标题设置为“application/json”,如下所示:

$http({
                    method:'POST',
                    data: $scope.user,
                    url:'http://localhost:60031/api/Default',
                    headers:{'Content-Type':'application/json'}
                }).success(function (data){
                        alert(JSON.stringify(data));
                    });

2) 让我们的 WebApi “CORS”(跨域),这就是最终答案。

https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多