如何使用.net web api保存对象

时间:2012-07-27 17:10:20

标签: c# windows-8 windows-runtime asp.net-web-api azure-sql-database

我在.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仍然是空的。错误在哪里?

8 个答案:

答案 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);
    }