在探索学习WebAPI的过程中,发现许多示例都解释了如何调用GET方法,但很少有文章详细说明如何向PUT/POST方法传递复杂输入,以及如何在服务端使用C#接收和处理这些数据。本文的目的就是详细解释这个过程。使用了.Net框架4.0进行代码演示,并在本文中使用了JSON。
今天,将向展示如何调用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();
}
现在服务已经自托管,让创建一个客户端应用程序来消费服务。这也将是一个控制台应用程序。
在与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);
}
}
}
就是这样。完成了:)。
必须运行TrialWebAPI,客户端才能调用服务。因此,首先运行TrialWebAPI项目。一旦它启动并运行,启动客户端,就可以看到结果。这是输出的截图。