自从升级到RC的WebAPI,我有一些真正奇怪的问题时调用POST在我的WebAPI。
我甚至回到了在新项目上生成的基本版本。所以:
public void Post(string value)
{
}
提琴手喊道:
Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29
Body:
{
"value": "test"
}
当我调试时,字符串“value”永远不会被赋值。它总是NULL。
有人有这个问题吗?
(我第一次看到这个问题是在一个更复杂的类型上)
这个问题不仅仅局限于ASP。在asp.net MVC 4中,同样的问题出现在一个新的ASP。NET MVC 3项目后RC安装
我对此很晚了,但也有类似的问题,在经过一天的大量回答和背景资料后,我找到了最简单/轻量级的解决方案,将一个或多个参数传递回Web API 2 Action如下:
这里假设您知道如何使用正确的路由设置Web API控制器/动作,如果不知道,请参考:https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api。
首先是控制器动作,这个解决方案还需要Newtonsoft。Json库。
[HttpPost]
public string PostProcessData([FromBody]string parameters) {
if (!String.IsNullOrEmpty(parameters)) {
JObject json = JObject.Parse(parameters);
// Code logic below
// Can access params via json["paramName"].ToString();
}
return "";
}
客户端使用jQuery
var dataToSend = JSON.stringify({ param1: "value1", param2: "value2"...});
$.post('/Web_API_URI', { '': dataToSend }).done(function (data) {
console.debug(data); // returned data from Web API
});
我发现的关键问题是确保您只发送一个整体参数回Web API,并确保它没有名称,只有值{":dataToSend},否则您的值将在服务器端为空。
通过这种方式,您可以以JSON结构向Web API发送一个或多个参数,并且不需要在服务器端声明任何额外的对象来处理复杂的数据。JObject还允许您动态遍历传入的所有参数,以便在参数随时间变化时实现更容易的可伸缩性。希望这能帮助像我一样挣扎的人。
如果您正在为Xml Formatter或JSON Formatter使用DataContractSerializer,则需要摆脱它。
我在我的WebApiConfig文件中有这个:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.UseDataContractJsonSerializer = true;
}
我简单地注释掉了jsonFormatter。UseDataContractJsonSerializer = true;并且我的输入参数不再为空。感谢《亡命之徒》给了我一个提示。
尝试创建一个类作为数据模型,然后发送一个具有与数据模型类属性匹配的属性的JSON对象。(注:我已经测试了这个,它与我今天刚刚下载的最新的MVC 4 RC 2012一起工作)。
public HttpResponseMessage Post(ValueModel model)
{
return Request.CreateResponse<string>(HttpStatusCode.OK, "Value Recieved: " + model.Value);
}
public class ValueModel
{
public string Value { get; set; }
}
下面的JSON对象以HTTP-POST正文形式发送,内容类型为application/ JSON
{ "value": "In MVC4 Beta you could map to simple types like string, but testing with RC 2012 I have only been able to map to DataModels and only JSON (application/json) and url-encoded (application/x-www-form-urlencoded body formats have worked. XML is not working for some reason" }
我认为必须创建数据模型类的原因是假定简单值来自url参数,而假定单个复杂值来自主体。它们确实有[FromBody]和[FromUrl]属性,但使用[FromBody]字符串值仍然不适合我。看起来他们还在解决很多bug,所以我相信这在未来会改变。
编辑:
让XML在主体中工作。默认的XML序列化器被更改为DataContractSerializer而不是XmlSerializer。在我的全局中放入以下一行。Asax文件修复了这个问题(参考)
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
在Angular中,我可以这样传递数据:
data: '=' + JSON.stringify({ u: $scope.usrname1, p: $scope.pwd1 }),
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }
在Web API控制器中:
[HttpPost]
public Hashtable Post([FromBody]string jsonString)
{
IDictionary<string, string> data = JsonConvert.DeserializeObject<IDictionary<string, string>>(jsonString);
string username = data["u"];
string pwd = data["p"];
......
或者,我也可以像这样发布JSON数据:
data: { PaintingId: 1, Title: "Animal show", Price: 10.50 }
并且,在控制器中,接受这样的类类型:
[HttpPost]
public string POST(Models.PostModel pm)
{
....
}
两种方式都可以,如果你在API中有一个已经建立的公共类,那么就发布JSON,否则就发布'=' + JSON.stringify({..:…, . .:…})
这招对我很管用:
Create a C# DTO class, with a property for every attribute you want to pass from jQuery/Ajax
public class EntityData
{
public string Attr1 { get; set; }
public string Attr2 { get; set; }
}
Define the web api method:
[HttpPost()]
public JObject AddNewEntity([FromBody] EntityData entityData)
{
Call the web api as such:
var entityData = {
"attr1": "value1",
"attr2": "value2"
};
$.ajax({
type: "POST",
url: "/api/YOURCONTROLLER/addnewentity",
async: true,
cache: false,
data: JSON.stringify(entityData),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
...
}
});