Angular2 HTTP Post ASP.NET MVC Web API

时间:2016-03-29 15:23:43

标签: asp.net asp.net-web-api angular asp.net-web-api2 restangular

如何使用Angular2正确创建复杂对象或多个参数的Web API POST?

我在Angular2中有一个服务组件,如下所示:

public signin(inputEmail: string, inputPassword: string): Observable<Response> {
    return this.http.post('/api/account/signin', JSON.stringify({ Email: inputEmail, Password: inputPassword}), this.options);
}

目标网络api如下所示:

[HttpPost]
[Route("signin")]
public async Task<IActionResult> Signin(string email, string password)
{
       ....
}

这不起作用,因为我需要将web api的参数转换为具有Email和Password属性的单个POCO类实体,并放置[FromBody]属性:Signin([FromBody] Credential credential)

不使用[FromURI](带有查询字符串的POST请求?),如何在不将这些参数转换为单个POCO类的情况下对多个参数或复杂对象进行POST?

因为如果我有许多带有(string sensitiveInfo1, string name, int sensitiveInfo2)(ClassifiedInfo info, string sensitiveInfo1, string sensitiveInfo2)等参数的Web API POST操作,我是否需要将它们全部转换为POCO类并始终使用[FromBody]?

PS。 我之前使用的是RestangularJS,它可以发布任何内容(多个原始对象和复杂对象),而我的Web API操作没有[FromBody]属性。将研究RestangularJS如何做到这一点。

7 个答案:

答案 0 :(得分:11)

  

不使用[FromURI](带有查询字符串的POST请求?),如何在不将这些参数转换为单个POCO类的情况下对多个参数或复杂对象进行POST?

我知道它不是你想听到的,但开箱即用这是不可能的。它不是发出请求的浏览器代码的限制。这意味着你使用Angular,JQuery,直接JavaScript,甚至是RestangularJS并不重要。这是Web API(任何版本)的限制(我使用那个词,因为我确信这是设计)。以下是有关此设计的文档:Mike Wasson撰写的Parameter Binding in ASP.NET Web API

  

最多允许一个参数从邮件正文中读取。所以这不起作用:

// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

所以问题就变成了,你有什么选择?

创建模型

这是你试图避免的事情,但我先列出它,因为这就是Web API的行为方式。我还没有听到一个令人信服的理由不这样做。此方法允许您轻松扩展模型,而无需更改方法签名。它还允许对模型本身进行模型验证。我个人非常喜欢这种方法。

public class SignInModel{
    public string Email {get;set;}
    public string Password {get;set;}
}

[HttpPost]
[Route("signin")]
public async Task<IActionResult> Signin(SignInModel signInModel)
{
       // ....
}

我没有重复您现有的JavaScript代码,因为您使用的是上述网络API代码

URL

再一次,你试图避免的。这确实可以实现您想要的限制,您必须使用URL上的查询字符串传递这些参数。 JavaScript会发生变化,但您在Web API方法上的签名不会改变。

public signin(inputEmail: string, inputPassword: string): Observable<Response> {
    return this.http.post('/api/account/signin/?email=inputEmail&password=inputPassword', null, this.options);
}

我没有重复您现有的Web API代码,因为您使用上述Web JavaScript代码(默认情况下,我相信默认为FromUri)

自定义模型活页夹

见Rick Strahl的Passing multiple POST parameters to Web API Controller Methods。此选项允许您创建可以执行您要求的自定义模型绑定器。这是一大堆额外的代码虽然,恕我直言,没有太大的好处。也许有些情况会有用,虽然我真的想不出任何不可思议的事情。

动态

最后,您还可以传入dynamic对象作为Web API的参数。这与将JSON作为字符串接收并使Controller代码负责内容的反序列化基本相同。同样,我认为这会使您的代码在大多数情况下变得更糟,因为您必须实现自定义验证和类型检查。这个答案是previously on SO by Bes Ley提出的。同样,也许有些情况会有用,虽然我真的想不出任何偏见。

答案 1 :(得分:4)

如果从Angular 2类型脚本调用Web API 2.2 post方法,请不要忘记添加以下标题内容和参数对象。

let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }); 
 var params = new URLSearchParams();
        params.set('userid', '102');
        params.set('username', 'foo');

 return this._http.post('http://localhost:6579/api/PostUser', params.toString(), { headers: headers }).map(res => res.json());

答案 2 :(得分:2)

也许您应该发布选项:

{ 
   headers: new Headers({
   'Content-Type': 'application/x-www-form-urlencoded'
   })
}

并对数据进行编码,如

jQuery.param({user:'bla', password: 'bla'});

答案 3 :(得分:2)

WebAPI不提供开箱即用的功能。如果您试图了解Web API绑定,您可能能够找出原因。

我认为this article可能有所帮助。

  

通用规则是:

     

- 默认情况下,从URI读取简单的字符串可转换参数(值类型,字符串,Guids,DateTimes等)

     

- 默认情况下,从正文中读取复杂类型

     

- 默认情况下,从身体中读取简单参数的集合

     

- 你不能根据来自URI和请求体的输入组成单个模型,它必须是一个或另一个

答案 4 :(得分:1)

   

我已修复Angular2 HTTP Post ASP.NET MVC Web API的问题

let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
let params: URLSearchParams = new URLSearchParams();
params.set('value', '2');

let options = new RequestOptions({
    headers: headers//,
    //search: params
});
let content = new URLSearchParams();
content.set('StudentName', 'Inderjit Singh';
content.set('Mobile', '+919041165398');            
content.set('Nationality', 'Indian');
content.set('AdmissionNo', '6');
content.set('SectionCode', '1');
content.set('Gender', 'Male');
content.set('RegNo', '18585');
content.set('ClassCode', '1');
this.http.post('YOUR_URL', content.toString(), { headers: headers }).map((res: Response) => { console.log("data is==>" + res.text()); }).subscribe();

答案 5 :(得分:0)

如果JSON对象具有相同的字段名称,WebApi将能够反序列化您的Credential对象(我不确定案例,因此您可能就在这里)。你似乎错过了Angular2组件中post调用的标题。

您可以使用Chrome调试器或Fiddler查看内容类型吗?它应该是application / json。

答案 6 :(得分:0)

尝试此操作,将复杂的类对象传递给单个数据参数。

var SearchQuery = function () {
    this.Alphabet = null;
    this.Search = false;
    this.Keyword = null;
    this.RegionList = null;
};
var para = new SearchQuery();
{ data: JSON.stringify(para) } - Post Data

您可以在API控制器中使用JObject接收它,并根据您的类反序列化它。