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 是如何做到的。
【问题讨论】:
既然你已经用email
和password
定义了动作的参数,e
和p
小写,我认为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 请求标头