3

我在 .net 中创建了 WebAPI(我的第一个)。使用这个 api 从数据库中获取对象、查询数据库等对我来说很容易。没什么新鲜的

但我想知道如何使用这个 webapi 保存一个对象?

我有一个与我的 webapi 通信的 clinet 应用程序(平板电脑、手机、PC)。从我的应用程序中可以保存用户新闻。现在我需要将它保存在数据库中。我使用 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);

但我不知道如何发送对象?我应该序列化它吗?如果是,如何通过邮寄方式发送。

// 更新

我已经构建了这个

        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 中,变量为空

这是来自我的 api 的代码

    // POST sd/Localization/insert
    public void Post(string test)
    {
        Console.WriteLine(test);
    }

“测试”变量为空。我究竟做错了什么 ?

// 更新 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 中的参数仍然为空。错误在哪里?

4

8 回答 8

6

WebAPI非常擅长解析发送给它的数据并将其转换为 .NET 对象。

我不习惯使用带有 WebAPI 的 C# 客户端,但我会尝试以下方法:

var client = new HttpClient();
client.PostAsJsonAsync<YourObjectType>("uri", yourObject);

注意:您需要使用System.Net.Http(来自具有相同名称的程序集)以及System.Net.Http.Formatting(也来自具有相同名称的程序集)为此。

于 2012-07-27T17:22:03.120 回答
3

该类HttpRequestMessage有一个名为(抽象类)Content类型的属性。HttpContent您可以在那里设置请求正文。例如,您可以在此处设置 JSON 内容,然后将其发送到 API:

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri) { 

    Content = new StringContent("{'Name':'Foo', 'Surname':'Bar'}")
};

您还可以使用格式化功能并将 CLR 对象提供给格式化程序ObjectContent并将序列化委托给格式化程序。

这里有很多关于 HttpClient 和 Web API 的示例:http: //blogs.msdn.com/b/henrikn/archive/2012/07/20/asp-net-web-api-sample-on-codeplex.aspx

于 2012-07-27T22:49:42.013 回答
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 并将内容发布到您的控制器方法:

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;
    }
}

我还建议看一下创建支持 CRUD 操作的 Web API,它涵盖了您所描述的场景,特别是创建资源部分。

于 2012-07-27T23:12:52.653 回答
1

我想我找到了解决方案,这就是为什么我将其发布为答案而不是评论,以便以后的任何讨论都可以分组。

如果我这样发送请求

using(HttpClient client = new HttpClient()) {
    await client.PostAsync(uri, new StringContent("my own string");
}

比我可以在我的 webapi 中得到它

await Request.Content.ReadAsStringAsync();

IMO 这不是完美的解决方案,但至少我正在追踪。我看到函数定义中的参数只有在我发送 POST 请求时才能在 URL 中获得。

当我使用比 String 更复杂的对象时,这个解决方案可能也会起作用(我还没有检查过)。

来自某人的任何想法。您认为这是一个好的解决方案吗?

于 2012-07-29T14:39:34.543 回答
1

我希望这将是您正在寻找的。

我创建了一个通用帖子,它将接受任何对象并将其发布到
客户端

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);
    }
于 2014-10-20T18:05:53.730 回答
0

我不熟悉 HttpClient(我相信它是 .NET 4.5),但 WebAPI 背后的概念是使用标准的 RESTful 结构。如果要通过 WebAPI 插入对象,则需要向服务发送 POST 请求。您应该将对象的内容放入请求的 BODY 中。

于 2012-07-27T17:27:36.543 回答
0

将空构造函数添加到您的 webapi 模型人员。这将为您节省我浪费在试图弄清楚为什么我的对象为空的所有时间。序列化(我想是反序列化)需要默认构造函数。

于 2014-03-25T16:51:46.227 回答
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;
    }
}

全部做完 !

于 2014-06-30T04:13:54.343 回答