Angular2 HTTP Post ASP.NET MVC Web API

Posted

技术标签:

【中文标题】Angular2 HTTP Post ASP.NET MVC Web API【英文标题】: 【发布时间】:2016-07-17 06:11:15 【问题描述】:

如何使用 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);

目标 web api 如下所示:

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

       ....

这不起作用,因为我需要将 web api 的参数转换为具有电子邮件和密码属性的单个 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 是如何做到的。

【问题讨论】:

既然你已经用emailpassword定义了动作的参数,ep小写,我认为javascript代码应该是相同的,例如: JSON.stringify( email: inputEmail, password: inputPassword). @FelipeOriani 对于使用 JSON.Net 作为 JSON 序列化程序的 .NET 来说,情况并非如此。默认情况下不区分大小写。 【参考方案1】:

WebApi 将能够反序列化您的 Credential 对象,前提是 JSON 对象具有相同的字段名称(我不确定大小写,所以您可能就在这里)。您似乎缺少 Angular2 组件中 post 调用的标题。

您可以使用 Chrome 调试器或 Fiddler 检查 Content-Type 吗?它应该是 application/json。

【讨论】:

我在 options 参数上添加了标题。我的问题是,如果您的 post 参数只有三个字符串,您是否仍应始终将它们转换为单个对象? 帖子上的查询字符串通常用于指定应如何处理发布的正文。如果你在服务器上持久化任何东西,或者改变任何东西,请使用 body 和 poco。我会使用多个轻量级的 pocos,这被认为是好的设计。例如,ServiceStack 实际上将路由映射到 Pocos。 github.com/ServiceStack/ServiceStack/wiki/Routing 有帮助吗? 有点。但我见过其他一些 3rd 方 js 框架可以发布到具有多个复杂参数的 web api,而无需使用 [FromBody](例如 restangular)【参考方案2】:

试试这个,将复杂的类对象传递给单个数据参数。

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 接收它,并根据您的类对其进行反序列化。

【讨论】:

【参考方案3】:

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

我知道这不是您想听到的,但开箱即用这是不可能的。发出请求的浏览器代码不受限制。这意味着无论您使用的是 Angular、JQuery、直接 JavaScript 还是 RestangularJS 都无关紧要。这是 Web API(任何版本)的限制(我使用这个词很松散,因为我确信这是设计使然)。以下是有关此设计的文档:Parameter Binding in ASP.NET Web API,作者为 Mike Wasson。

最多允许从消息体中读取一个参数。所以这行不通:

// 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 代码,因为您所拥有的与上述 web api 代码一样工作

网址

再一次,你试图避免的事情。这确实使您想要的成为可能,但您必须使用 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 作为字符串并让您的控制器代码负责内容的反序列化相同。同样,我相信这会使您的代码在大多数情况下变得更糟,因为您必须实现自定义验证和类型检查。这个答案是previously on SO by Bes Ley提出的。同样,也许在某些情况下它会很有用,尽管我真的想不出任何东西。

【讨论】:

这是现场。无论您使用哪种 javascript 框架,它们都使用相同的协议 (http),该协议有其规则和限制。【参考方案4】:

也许你应该发布选项:

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

像这样对数据进行编码

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

【讨论】:

【参考方案5】:

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

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

一般规则是:

– 简单的、字符串可转换的参数(值类型、字符串、Guids、DateTimes 等)默认从 URI 读取

– 复杂类型默认从正文中读取

– 默认情况下,简单参数的集合也是从正文中读取的

– 你不能基于来自 URI 和请求正文的输入来组合单个模型,它必须是一个或另一个

【讨论】:

【参考方案6】:

如果你从 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());

【讨论】:

【参考方案7】:

我已经修复了 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();

【讨论】:

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

以上是关于Angular2 HTTP Post ASP.NET MVC Web API的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有表单数据主体而不是 json 主体的 http 'POST'? (Angular2/打字稿)

Angular2 HTTP Post ASP.NET MVC Web API

Angular2 HTTP POST发生错误SyntaxError:JSON输入意外结束

在 Angular2 HTTP POST 中设置 JSON 请求标头

Angular2 http post请求到另一个端口上的nodejs服务器

从Angular2应用程序发送http post请求时如何启用CORS