我在.net(我的第一个)中创建了WebAPI。使用这个api从db获取对象,查询db等对我来说很容易。没什么新的
但我想知道如何使用此webapi保存对象?
我有一个与我的webapi通信的clinet应用程序(平板电脑,手机,PC)。从我的应用程序中可以保存用户新闻。现在我需要将其保存在db中。我使用Azure SQL。现在我如何将此对象传递给API,以便保存它?
对于我的应用程序,我使用C#/ XAML 对于我的WebAPI,我使用.NET
我正在使用这段代码:
HttpClient httpClient = new HttpClient();
String u = this.apiUrl + "sd/Localization/insert";
Uri uri = new Uri(u);
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
但我不知道如何发送对象?我应该序列化吗?如果是,如何通过邮寄发送。
// UPDATE
我已经构建了这个
HttpClient httpClient = new HttpClient();
String u = this.apiUrl + "sd/Localization/insert";
Uri uri = new Uri(u);
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
httpRequestMessage.Content = new StringContent("{'Name':'Foo', 'Surname':'Bar'}");
await httpClient.PostAsync(uri, httpRequestMessage.Content);
但在我的API中,变量为null
这是我api的代码
// POST sd/Localization/insert
public void Post(string test)
{
Console.WriteLine(test);
}
“test”变量为null。 我做错了什么?
//更新2
using (HttpClient httpClient = new HttpClient())
{
String u = this.apiUrl + "sd/Localization/insert";
Uri uri = new Uri(u);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri)
{
Method = HttpMethod.Post,
Content = new StringContent("my own test string")
};
await httpClient.PostAsync(uri, request.Content);
}
路由配置
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "sd/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
在你所有答案之后我创造了这个,但我的api中的param仍然是空的。错误在哪里?
答案 0 :(得分:6)
WebAPI 非常善于解析发送给它的数据并将其转换为.NET对象。
我不习惯使用带有WebAPI的C#客户端,但我会尝试以下操作:
var client = new HttpClient();
client.PostAsJsonAsync<YourObjectType>("uri", yourObject);
注意:您需要使用System.Net.Http
(来自具有相同名称的程序集)以及System.Net.Http.Formatting
(也来自具有相同名称的程序集)。
答案 1 :(得分:3)
HttpRequestMessage
类有一个名为Content
的属性,其类型为HttpContent
(抽象类)。您可以在那里设置请求正文。例如,您可以在那里设置JSON内容,然后将其发送到API:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri) {
Content = new StringContent("{'Name':'Foo', 'Surname':'Bar'}")
};
您还可以使用格式化功能并将CLR对象提供给ObjectContent
,并将序列化委派给Formatter。
HttpClient和Web API上有很多样本:http://blogs.msdn.com/b/henrikn/archive/2012/07/20/asp-net-web-api-sample-on-codeplex.aspx
答案 2 :(得分:3)
假设您的Web API控制器上有一个支持POST操作的操作方法,该操作类似于:
[HttpPost()]
public HttpResponseMessage Post(YourObjectType value)
{
try
{
var result = this.Repository.Add(value);
var response = this.Request.CreateResponse<YourObjectType>(HttpStatusCode.Created, result);
if (result != null)
{
var uriString = this.Url.Route(null, new { id = result.Id });
response.Headers.Location = new Uri(this.Request.RequestUri, new Uri(uriString, UriKind.Relative));
}
return response;
}
catch (ArgumentNullException argumentNullException)
{
throw new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.BadRequest)
{
ReasonPhrase = argumentNullException.Message.Replace(Environment.NewLine, String.Empty)
}
);
}
}
您可以使用HttpClient将对象序列化为JSON并将内容POST到您的控制器方法:
using (var client = new HttpClient())
{
client.BaseAddress = baseAddress;
client.Timeout = timeout;
using (var response = client.PostAsJsonAsync<YourObjectType>("controller_name", yourObject).Result)
{
if (!response.IsSuccessStatusCode)
{
// throw an appropriate exception
}
result = response.Content.ReadAsAsync<YourObjectType>().Result;
}
}
我还建议您查看Creating a Web API that Supports CRUD Operations,其中介绍了您所描述的方案,特别是创建资源部分。
答案 3 :(得分:1)
我想我找到的解决方案就是为什么我发布这个作为答案而不是评论,所以以后的讨论可以分组。
如果我发送此类请求
using(HttpClient client = new HttpClient()) {
await client.PostAsync(uri, new StringContent("my own string");
}
我可以从我的webapi中获取它
await Request.Content.ReadAsStringAsync();
IMO这不是完美的解决方案,但至少我正在追踪。我看到函数定义中的参数只有在我发送POST请求时才能获得URL。
当我使用更复杂的对象然后String时,这个解决方案也可能会工作(我还没有检查)。
某人的任何想法。你认为这是一个很好的解决方案吗?
答案 4 :(得分:0)
我不熟悉HttpClient(我相信它是.NET 4.5),但WebAPI背后的概念是使用标准的RESTful结构。如果要通过WebAPI插入对象,则需要向服务发送POST请求。您应该将对象的内容放入请求的BODY中。
答案 5 :(得分:0)
将空构造函数添加到webapi模型人员中。这将节省你我浪费的所有时间试图找出我的对象为空的原因。 序列化(以及我认为的反序列化)需要默认构造函数。
答案 6 :(得分:0)
这是我的方式。这是成功的。我希望它有所帮助 Fisrt:你必须拥有的所有图书馆。你可以从nuget下载
使用Newtonsoft.Json; 和 使用Newtonsoft.Json.Linq;
HttpClient client = new HttpClient();
//this is url to your API server.in local.You must change when u pushlish on real host
Uri uri = new Uri("http://localhost/");
client.BaseAddress = uri;
//declared a JArray to save object
JArray listvideoFromUser = new JArray();
//sample is video object
VideoModels newvideo = new VideoModels();
//set info to new object..id/name...etc.
newvideo._videoId = txtID.Text.Trim();
//add to jArray
listvideoFromUser.Add(JsonConvert.SerializeObject(newvideo));
//Request to server
//"api/Video/AddNewVideo" is router of API .you must change with your router
HttpResponseMessage response =client.PostAsJsonAsync("api/Video/AddNewVideo", listvideoFromUser).Result;
if (response.IsSuccessStatusCode){
//show status process
txtstatus.Text=response.StatusCode.ToString();
}
else{
//show status process
txtstatus.Text=response.StatusCode.ToString();
}
服务器端:
[Route("api/Video/AddNewVideo")]
[System.Web.Http.HttpPost]
public HttpResponseMessage AddNewVideo(JArray listvideoFromUser){
if (listvideoFromUser.Count > 0){
//DeserializeObject: that object you sent from client to server side.
//Note:VideoModels is class object same as model of client side
VideoModels video = JsonConvert.DeserializeObject<VideoModels>(listvideoFromUser[0].ToString());
//that is just method to save database
Datacommons.AddNewVideo(video);
//show status for client
HttpResponseMessage response = new HttpResponseMessage { StatusCode = HttpStatusCode.Created };
return response;
}
else{
HttpResponseMessage response = new HttpResponseMessage { StatusCode = HttpStatusCode.InternalServerError };
return response;
}
}
全部完成!
答案 7 :(得分:0)
我希望这就是你要找的东西。
我创建了一个接受任何对象并发布它的通用帖子
客户端
public async Task<HttpResponseMessage> Post<T>(string requestUri, T newObject) where T : class
{
using (var client = new HttpClient())
{
client.BaseAddress = this.HttpClientAddress;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = JsonConvert.SerializeObject(newObject, this.JsonSerializerSettings);
var clientAsync = await client.PostAsync(requestUri, new StringContent(content, Encoding.UTF8, "application/json"));
clientAsync.EnsureSuccessStatusCode();
return clientAsync;
}
}
对此的调用就像
一样简单public async Task<int> PostPerson(Models.Person person)
{
//call to the generic post
var response = await this.Post("People", person);
//get the new id from Uri api/People/6 <-- this is generated in the response after successful post
var st = response.Headers.Location.Segments[3];
//do whatever you want with the id
return response.IsSuccessStatusCode ? JsonConvert.DeserializeObject<int>(st) : 0;
}
此外,如果您的用例需要,您可以使用ReadAsStringAsync()在帖子后读取对象。
服务器端
// POST: api/People
public IHttpActionResult Post(Models.Person personDto)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var person = new Entities.Person
{
FirstName = personDto.FirstName,
LastName = personDto.LastName,
DateOfBirth = personDto.DateOfBirth,
PreferedLanguage = personDto.PreferedLanguage
};
_db.Persons.Add(person);
_db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = person.Id }, personDto);
}