ASP.NET Web API در سمت سرور، برای مدیریت ApiControllerها و در سمت کلاینتهای دات نتی آن، برای مدیریت HttpClient، به صورت پیش فرض از JSON.NET استفاده میکند. در ادامه نگاهی خواهیم داشت به تنظیمات JSON در سرور و کلاینتهای ASP.NET Web API.
آماده سازی یک مثال Self host
برای اینکه خروجیهای JSON را بهتر و بدون نیاز به ابزار خاصی مشاهده کنیم، میتوان یک پروژهی کنسول جدید را آغاز کرده و سپس آنرا تبدیل به Host مخصوص Web API کرد. برای اینکار تنها کافی است در کنسول پاور شل نیوگت دستور ذیل را صادر کنید:
PM> Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
سپس کنترلر Web API ما از کدهای ذیل تشکیل خواهد شد که در آن در متد Post، قصد داریم اصل محتوای دریافتی از کاربر را نمایش دهیم. توسط متد GetAll آن، خروجی نهایی JSON آن در سمت کاربر بررسی خواهد شد.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
namespace WebApiSelfHostTests
{
public class UsersController : ApiController
{
public IEnumerable<User> GetAllUsers()
{
return new[]
{
new User{ Id = 1, Name = "User 1", Type = UserType.Admin },
new User{ Id = 2, Name = "User 2", Type = UserType.User }
};
}
public async Task<HttpResponseMessage> Post(HttpRequestMessage request)
{
var jsonContent = await request.Content.ReadAsStringAsync();
Console.WriteLine("JsonContent (Server Side): {0}", jsonContent);
return new HttpResponseMessage(HttpStatusCode.Created);
}
}
}
که در آن شیء کاربر چنین ساختاری را دارد:
namespace WebApiSelfHostTests
{
public enum UserType
{
User,
Admin,
Writer
}
public class User
{
public int Id { set; get; }
public string Name { set; get; }
public UserType Type { set; get; }
}
}
برای اعمال تنظیمات self host ابتدا نیاز است یک کلاس Startup مخصوص Owin را تهیه کرد:
using System.Web.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Owin;
namespace WebApiSelfHostTests
{
/// <summary>
/// PM> Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
/// </summary>
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
که سپس با فراخوانی چند سطر ذیل، سبب راه اندازی سرور Web API، بدون نیاز به IIS خواهد شد:
var server = WebApp.Start<Startup>(url: BaseAddress);
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
server.Dispose();
در ادامه اگر در سمت کلاینت، دستورات ذیل را برای دریافت لیست کاربران صادر کنیم:
using (var client = new HttpClient())
{
var response = client.GetAsync(BaseAddress + "api/users").Result;
Console.WriteLine("Response: {0}", response);
Console.WriteLine("JsonContent (Client Side): {0}", response.Content.ReadAsStringAsync().Result);
}
به این خروجی خواهیم رسید:
JsonContent (Client Side): [{"Id":1,"Name":"User 1","Type":1},{"Id":2,"Name":"User 2","Type":0}]
همانطور که ملاحظه میکنید، مقدار Type مساوی صفر است. در اینجا چون Type را به صورت enum تعریف کردهایم، به صورت پیش فرض مقدار عددی عضو انتخابی در JSON نهایی درج میگردد.
تنظیمات JSON سمت سرور Web API
برای تغییر این خروجی، در سمت سرور تنها کافی است به کلاس Startup مراجعه و HttpConfiguration را به صورت ذیل تنظیم کنیم:
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings
{
Converters = { new StringEnumConverter() }
};
در اینجا با انتخاب StringEnumConverter، سبب خواهیم شد تا کلیه مقادیر enum، دقیقا مساوی همان مقدار اصلی رشتهای آنها در JSON نهایی درج شوند.
اینبار اگر برنامه را اجرا کنیم، چنین خروجی حاصل میگردد و در آن دیگر Type مساوی صفر نیست:
JsonContent (Client Side): [{"Id":1,"Name":"User 1","Type":"Admin"},{"Id":2,"Name":"User 2","Type":"User"}]
تنظیمات JSON سمت کلاینت Web API
اکنون در سمت کلاینت قصد داریم اطلاعات یک کاربر را با فرمت JSON به سمت سرور ارسال کنیم. روش متداول آن توسط کتابخانهی HttpClient، استفاده از متد PostAsJsonAsync است:
var user = new User
{
Id = 1,
Name = "User 1",
Type = UserType.Writer
};
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsJsonAsync(BaseAddress + "api/users", user).Result;
Console.WriteLine("Response: {0}", response);
با این خروجی سمت سرور
JsonContent (Server Side): {"Id":1,"Name":"User 1","Type":2}
در اینجا نیز Type به صورت عددی ارسال شدهاست. برای تغییر آن نیاز است به متدی با سطح پایینتر از PostAsJsonAsync مراجعه کنیم تا در آن بتوان JsonMediaTypeFormatter را مقدار دهی کرد:
var jsonMediaTypeFormatter = new JsonMediaTypeFormatter
{
SerializerSettings = new JsonSerializerSettings
{
Converters = { new StringEnumConverter() }
}
};
var response = client.PostAsync(BaseAddress + "api/users", user, jsonMediaTypeFormatter).Result;
Console.WriteLine("Response: {0}", response);
خاصیت SerializerSettings کلاس JsonMediaTypeFormatter برای اعمال تنظیمات JSON.NET پیش بینی شدهاست.
اینبار مقدار دریافتی در سمت سرور به صورت ذیل است و در آن، Type دیگر عددی نیست:
JsonContent (Server Side): {"Id":1,"Name":"User 1","Type":"Writer"}
مثال کامل این بحث را از اینجا میتوانید دریافت کنید:
UsersController.zip