深入理解WebAPI复杂类型输入与处理

在探索学习WebAPI的过程中,发现许多示例都解释了如何调用GET方法,但很少有文章详细说明如何向PUT/POST方法传递复杂输入,以及如何在服务端使用C#接收和处理这些数据。本文的目的就是详细解释这个过程。使用了.Net框架4.0进行代码演示,并在本文中使用了JSON。

创建WebAPI项目

今天,将向展示如何调用WebAPI的PUT方法,该方法接受复杂类型作为输入。首先,从创建一个空的WebAPI项目开始。

创建WebAPI项目的过程在此不赘述,因为有很多相关文章。将WebAPI项目命名为TrialWebAPI。项目创建完成后,添加一个控制器。为此,右键单击Controllers文件夹,选择Add -> Controller。这将打开"Add Controller"对话框。将控制器命名为Trial,并选择了下图所示的模板,然后点击Add。这将添加控制器。

新添加的控制器将具有默认的动作方法:

// PUT api/data/5 public void Put(int id, [FromBody]string value) { }

现在,是时候创建将作为输入传递给此动作方法的复杂类型了。将创建一个名为Person的复杂类型。在Models文件夹中添加一个类,并将其命名为Person。为该类添加一些属性。这是Person类版本:

public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string FullName { get; set; } public int Age { get; set; } }

可以通过使用HttpRequestMessage或ModelBinder来使PUT方法接收复杂类型。本文将展示如何使用ModelBinder,因为它将保持代码的清洁和与正在处理的复杂对象相关。将很快发布一篇关于HttpRequestMessage的文章。

为了使用ModelBinder,需要实现IModelBinder接口。这个接口在System.Web.Http.ModelBinding命名空间下。IModelBinder定义了一个名为BindModel的方法。让为复杂类型Person创建一个ModelBinder。

在Models文件夹中添加一个新类,并将其命名为PersonModelBinder。实现IModelBinder接口。这是PersonModelBinder版本:

public class PersonModelBinder : IModelBinder { public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType != typeof(Person)) { return false; } Person result = JsonConvert.DeserializeObject(actionContext.Request.Content.ReadAsStringAsync().Result); bindingContext.Model = result; return true; } }

代码非常简单且易于理解。由于这是一个示例,没有进行太多的验证。可以在这里添加验证逻辑。

注意:HttpActionContext需要System.Web.Http.Controllers命名空间,JsonConvert需要Newtonsoft.Json。

一旦完成,就必须让Person复杂类型知道PersonModelBinder将成为其ModelBinder。这是通过使用ModelBinder属性来完成的,如下所示:

[ModelBinder(typeof(PersonModelBinder))] public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string FullName { get; set; } public int Age { get; set; } }

现在是时候改变Put方法以接受Person复杂类型作为输入了。Put方法的新版本如下。返回类型已从void更改为HttpResponseMessage。此方法接收Person复杂类型作为输入,更新FullName并发送回Person对象。只是一个简单的示例。

// PUT api/data public HttpResponseMessage Put([ModelBinder]Person putPerson) { putPerson.FullName = string.Format("{0},{1}", putPerson.FirstName, putPerson.LastName); var output = JsonConvert.SerializeObject(putPerson); StringContent content = new StringContent(output, Encoding.UTF8, "application/json"); HttpResponseMessage message = Request.CreateResponse(HttpStatusCode.OK); message.Content = content; return message; }

移除了Id参数,因为不会使用它,并且更改了URI以反映这一点。现在WebAPI已经准备好了。将为演示目的在控制台应用程序中自托管服务。

创建控制台应用程序进行自托管

创建一个控制台应用程序并将其命名为APIHost。使用NuGet并安装Microsoft.AspNet.WebApi.SelfHost包到项目中。一旦包安装完成,将以下代码添加到Program.cs文件的Main方法中。

static void Main(string[] args) { HttpSelfHostConfiguration selfConfiguration = new HttpSelfHostConfiguration("http://localhost:51880/"); selfConfiguration.Routes.MapHttpRoute("API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional }); HttpSelfHostServer selfHostServer = new HttpSelfHostServer(selfConfiguration); selfHostServer.OpenAsync().Wait(); Console.WriteLine("Press Enter to quit"); Console.ReadLine(); }

现在服务已经自托管,让创建一个客户端应用程序来消费服务。这也将是一个控制台应用程序。

创建客户端访问WebAPI

在与APIHost相同的解决方案中添加一个新项目,并将其命名为APIClient。使用NuGet并安装Microsoft.AspNet.WebApi.Client包到此客户端项目中。将对APIHost的引用添加到APIClient项目中。将APIClient设置为启动项目。

由于Put方法期望Person复杂类型作为输入,必须从客户端发送一个Person。让在APIClient中添加一个新类,并将其命名为Person。就像在WebAPI中对Person类所做的那样,添加属性。APIClient中的Person类不会有ModelBinder属性。

public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string FullName { get; set; } public int Age { get; set; } }

离调用Put方法并显示输出只有一步之遥了。将以下代码添加到APIClient项目的Program.cs中。

class Program { static HttpClient client = new HttpClient(); static void Main(string[] args) { client.BaseAddress = new Uri("http://localhost:51880/"); PutTrial(); Console.ReadLine(); } private static void PutTrial() { Person person = new Person() { FirstName = "Iron", LastName = "Man", Age = 30 }; Console.WriteLine("Before calling the PUT method"); Console.WriteLine("-----------------------------"); Console.WriteLine("FirstName of the Person is : {0}", person.FirstName); Console.WriteLine("LastName of the Person is : {0}", person.LastName); Console.WriteLine("Fullname of the Person is : {0}", person.FullName); Console.WriteLine("Age of the Person is : {0}", person.Age); Console.WriteLine(); string serilized = JsonConvert.SerializeObject(person); var inputMessage = new HttpRequestMessage { Content = new StringContent(serilized, Encoding.UTF8, "application/json") }; inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage message = client.PutAsync("api/trial", inputMessage.Content).Result; if (message.IsSuccessStatusCode) { var inter = message.Content.ReadAsStringAsync(); Person reslutPerson = JsonConvert.DeserializeObject(inter.Result); Console.WriteLine("Person returned from PUT method:"); Console.WriteLine("--------------------------------"); Console.WriteLine("FirstName of the Person is : {0}", reslutPerson.FirstName); Console.WriteLine("LastName of the Person is : {0}", reslutPerson.LastName); Console.WriteLine("Fullname of the Person is : {0}", reslutPerson.FullName); Console.WriteLine("Age of the Person is : {0}", reslutPerson.Age); } } }

就是这样。完成了:)。

测试WebAPI

必须运行TrialWebAPI,客户端才能调用服务。因此,首先运行TrialWebAPI项目。一旦它启动并运行,启动客户端,就可以看到结果。这是输出的截图。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485