asp.net web api [FromBody]参数
Using jQuery to POST [FromBody] parameters to Web API
时间2013-04-04 00:28:17 Encosia原文 http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
ASP.NET Web API has been one of my favorite recent additions to ASP.NET. Whether you prefer a RESTful approach or something more RPC-oriented, Web API will do just about anything you need . Even if you’re still using ASP.NET WebForms, Web API still has you covered – a nice example of the “One ASP.NET” philosophy that’s finally beginning to come together.
However, ASP.NET Web API throws an unintuitive curveball at you when you want to accept simple primitive types as parameters to POST methods. Figuring this issue out is particularly confusing because it’s one of the rare parts of Web API that violates the principle of least astonishment .
Because of that, using jQuery to interact with those methods requires a slight contortion that seems strange at first, but makes sense once you understand why it’s necessary. In this post, I’ll briefly describe the underlying issue and show you how jQuery can be convinced to work around the issue.
POSTing primitive parameters to Web API
There are three things you need to know about Web API if you want to go the route of POSTing a primitive type (e.g. string, int, or bool) to a method. For example, say you’re working with this straightforward POST method in a Web API controller named ValuesController
:
// POST api/values
public string Post(string value) {
return value;
}
You might try POSTing a value into that Web API method using a standard jQuery$.post
, like this:
$.post('/api/values', { value: 'Dave' });
If you inspect the server’s response to that request, you’ll be greeted with a bewildering 404 error:
Confronted with that response, it’s only natural to treat the problem as an issue with your routing configuration and debug from there, but that’s not the issue.
1. Parameters must be marked as [FromBody]
As it turns out, the reason for that 404 error isn’t a routing problem. ASP.NET correctly identifies our ValuesController
as the controller to handle a POST to/api/values
, but it can’t locate an acceptable method to process the request.
The reason for that is a twofold mismatch between the required parameter that Web API expects to accompany requests to our Post
method and what we sent. The first of those mismatches is that the method’s parameter must be decorated with the[FromBody]
attribute.
[FromBody]
directs Web API to search for the parameter’s value in the body of a POST request. Adding that directive to our method is easy enough:
// POST api/values
public string Post([FromBody]string value) {
return value;
}
I can’t say that I understand why this extra hassle is necessary, especially since it wasn’t required in WCF Web API and preliminary versions of ASP.NET Web API , but it’s easy enough as long as you’re aware that it needs to be present.
Adding [FromBody]
fixes our 404 error, but things unfortunately still aren’t working quite right. Making the same request to it again works, but the value
parameter is coming back as null
now instead of the provided value:
2. Only one parameter per method
Speaking of the parameters to our method, another potentially confusing thing about accepting [FromBody]
parameters is that there can be only one .
Attempting to accept multiple parameters from the POST body will result in a (refreshingly decipherable) server-side error along these lines:
Can’t bind multiple parameters (‘foo’ and ‘bar’) to the request’s content.
It’s possible to circumvent this limitation by using manual parsing techniques, but that seems antithetical to Web API and model binding to me. If you want Web API to automatically convert POST data to your [FromBody]
input parameter, you have to limit yourself to only a single parameter.
I believe the thinking here is that, especially in a RESTful API, you’ll want to bind data to the single resource that a particular method deals with. So, pushing data into several loose parameters isn’t the sort of usage that Web API caters to.
This limitation can be a bit confusing when you’re coming from WebForms or MVC though, and trying work around it feels like going against the grain of the framework. So, if I need to accept more than one POST parameter, I just define a quick view model.
In other words, don’t try to do this:
public string Post([FromBody]string FirstName,
[FromBody]string LastName) {
return FirstName + " " + LastName;
}
Instead, work with the framework and do something like this if you need to accept more than a single parameter:
// DTO or ViewModel? Potato or potato, IMO.
public class PersonDTO {
public string FirstName { get; set; }
public string LastName { get; set; }
} public string Post(PersonDTO Person) {
return Person.FirstName + " " + Person.LastName;
}
3. [FromBody] parameters must be encoded as =value
The final hurdle remaining is that Web API requires you to pass [FromBody]
parameters in a particular format. That’s the reason why our value parameter was null in the previous example even after we decorated the method’s parameter with[FromBody]
.
Instead of the fairly standard key=value
encoding that most client- and server-side frameworks expect, Web API’s model binder expects to find the [FromBody]
values in the POST body without a key name at all. In other words, instead ofkey=value
, it’s looking for =value
.
This part is, by far, the most confusing part of sending primitive types into a Web API POST method. Not too bad once you understand it, but terribly unintuitive and not discoverable.
What not to do
Now that we’ve covered what you need to know about the server-side code, let’s talk about using jQuery to POST data to [FromBody]
parameters. Again, here’s the Web API method that we’re trying to POST data into:
// POST api/values
public string Post([FromBody]string value) {
return value;
}
You’ll have a hard time finding a jQuery $.post
(or $.ajax
) example that conforms to the =value
encoding approach. Typically, platform-agnostic jQuery documentation and tutorials suggest that one of these two approaches should work:
// Value will be null.
$.post('api/values', value); // Value will be null.
$.post('api/values', { key: value });
Unfortunately, neither of those work with Web API in the case of [FromBody]
parameters (the latter would work to send an object, rather than a single primitive value). In both cases, our method will be invoked, but the model binder won’t assign anything to value
and it will be null
.
Making it work
There are two ways to make jQuery satisfy Web API’s encoding requirement. First, you can hard code the =
in front of your value, like this:
$.post('api/values', "=" + value);
Personally, I’m not a fan of that approach. Aside from just plain looking kludgy, playing fast and loose with JavaScript’s type coercsion is a good way to find yourself debugging a “wat” situation .
Instead, you can take advantage of how jQuery encodes object parameters to$.ajax
, by using this syntax:
$.post('api/values', { '': value });
If the data parameter has properties with empty string keys, jQuery serializes those properties in the form of =value
. And, that’s exactly what we need to make Web API happy:
相关主题
如果你感兴趣
喜 欢 收 藏
分享该文章
分享到
该来源最新文章
- A cleaner way to use setTimeout and anonymous callbacks2014-02-14 03:26:54
- Button click handlers, AJAX, and premature submission2014-02-01 01:30:22
- Why malware in Chrome extensions was inevitable2014-01-22 17:30:45
- How to Chromecast video in a popup window2014-01-08 02:27:27
- Spoiled by Windows2013-12-11 04:25:23
请
asp.net web api [FromBody]参数的更多相关文章
- ASP.NET Web API 通过参数控制返回类型(JSON|XML)
一个很实用的技巧,可以在访问web api服务的时候指定返回数据的格式类型,比如 json 或者 xml. 因为 web api 默认返回的是XML格式,但是现在json 比较流行,同时网上也有其他的 ...
- Asp.Net Web API 2第十六课——Parameter Binding in ASP.NET Web API(参数绑定)
导航 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html. 本文主要来讲解以下内容: ...
- ASP.NET Web API中的参数绑定总结
ASP.NET Web API中的action参数类型可以分为简单类型和复杂类型. HttpResponseMessage Put(int id, Product item) id是int类型,是简单 ...
- Parameter Binding in ASP.NET Web API(参数绑定)
Parameter Binding in ASP.NET Web API(参数绑定) 导航 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnbl ...
- ASP.NET Web API 2 之参数验证
Ø 前言 目前 C# 比较流行使用 ASP.NET Web API 来承载 Web 接口,提供与客户端之间的数据交互,现在的版本已经是 2.0 了.既然是接口就少不了对输入参数的验证,所以本文主要探 ...
- 让ASP.NET Web API支持$format参数的方法
在不使用OData的情况下,也可以让ASP.NET Web API支持$format参数,只要在WebApiConfig里添加如下三行红色粗体代码即可: using System; using Sys ...
- [转]让ASP.NET Web API支持$format参数的方法
本文转自:http://www.cnblogs.com/liuzhendong/p/4228592.html 在不使用OData的情况下,也可以让ASP.NET Web API支持$format参数, ...
- ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档
原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...
- ASP.NET Web API - ASP.NET MVC 4 系列
Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF ...
随机推荐
- Python学习路程day4
迭代器&生成器 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退. ...
- C++实现python标准库中的Counter
看python standard library by exmple里面提到一个Counter容器,它像muliset一样,能够维持一个集合,并在常量时间插入元素.查询某个元素的个数,而且还提供了一个 ...
- (spring-第2回【IoC基础篇】)Spring的Schema,基于XML的配置
要深入了解Spring机制,首先需要知道Spring是怎样在IoC容器中装配Bean的.而了解这一点的前提是,要搞清楚Spring基于Schema的Xml配置方案. 在深入了解之前,必须要先明白几个标 ...
- php大力力 [021节]mysql表名在mac下不能大写
2015-08-27 php大力力021.mysql表名在mac下不能大写 刚才数据库里面,phpMyAdmin狂出错. Some errors have been detected on the s ...
- 前端开发者应该知道的 CSS 小技巧
一些小技巧让你的CSS技术更专业 使用:not()去除导航上不需要的边框 为body添加行高 垂直居中任何元素 逗号分离的列表 使用负nth-child选择元素 使用SVG图标 文本显示优化 在纯CS ...
- zf2-tutorial调通,坑爹的init_autoloader.php
zf2-tutorial的作者把init_autoloader.php内容写错了,新建个工程,把其中的这个文件的内容替一下,然后建库/建表,把local.ini打开(不是必须的),用户名/口令等配好, ...
- How to set up a basic working Appium test environment
Appium is a test framework targeting devices; although it is very handy and powerful, it is not so s ...
- 【转】SQL SERVER日志满或过大的处理方法
原文转自:http://blog.chinaunix.net/uid-7953959-id-2543262.html 事务日志文件Transaction Log File是用来记录数据库更新情况的文件 ...
- ASP.NET中的指令:
来源:http://www.cnblogs.com/zhuisha/archive/2008/07/02/1234222.html ASP.NET中的指令: @Page指令: @Page指令只能在.a ...
- NSNumber 、 NSValue 、 日期处理 、 集合类 、 NSArray(一)
1 基本数据类型的封装 1.1 问题 我们所学的所有基本数据类型,如int.float.double.char等,都不是对象,不能向它们发送消息.然而,在Foundation中的许多类,如NSArra ...