Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Content Negotiation ใน ASP.NET WebAPI C# คืออะไร

Content Negotiation (การเจรจาเนื้อหา) คือกระบวนการเลือก Representation ที่ดีที่สุดสำหรับ Response เมื่อมี Multiple Representations Available หมายถึง ขึ้นอยู่กับค่า Accept Header ใน Request Server จะส่ง Response กลับไป Mechanism หลักสำหรับ Content Negotiation ใน HTTP คือ Request Headers เหล่านี้:

  • Accept - Media Types ที่ยอมรับสำหรับ Response เช่น "application/json", "application/xml", หรือ Custom Media Type เช่น "application/vnd.example+xml"
  • Accept-Charset - Character Sets ที่ยอมรับ เช่น UTF-8 หรือ ISO 8859-1
  • Accept-Encoding - Content Encodings ที่ยอมรับ เช่น gzip
  • Accept-Language - ภาษาธรรมชาติกำหนด เช่น "en-us"

Server สามารถดูส่วนอื่นของ HTTP Request ได้ เช่น ถ้า Request มี Header X-Requested-With บ่งชี้ว่าเป็น AJAX Request Server อาจ Default เป็น JSON ถ้าไม่มี Accept Header

ใน Content Negotiation Pipeline จะได้ IContentNegotiator Service จาก HttpConfiguration Object และได้ List ของ Media Formatters จาก HttpConfiguration.Formatters Collection

Pipeline จะเรียก IContentNegotiator.Negotiate ส่งผ่าน:

  • Type ของ Object ที่จะ Serialize
  • Collection ของ Media Formatters
  • HTTP Request

เมธอด Negotiate คืนค่า 2 สิ่ง:

  • Formatter ใดที่จะใช้
  • Media Type สำหรับ Response

ถ้าไม่พบ Formatter Negotiate จะคืนค่า Null และ Client จะได้ HTTP Error 406 (Not Acceptable)

ตัวอย่าง StudentController


using DemoWebApplication.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace DemoWebApplication.Controllers {
    public class StudentController : ApiController {
        List students = new List {
            new Student { Id = 1, Name = "Mark" },
            new Student { Id = 2, Name = "John" }
        };
    }
}

Standard ของ RESTful Service คือ Client ควรมีความสามารถตัดสินใจรูปแบบ Response ที่ต้องการ - XML, JSON ฯลฯ Request ที่ส่งไป Server มี Accept Header ใช้ Accept Header Client ระบุ Format สำหรับ Response:


Accept: application/xml  → Returns XML
Accept: application/json → Returns JSON

ตัวอย่างผลลัพธ์

Accept: application/xml → Response เป็น XML

Content Negotiation ใน ASP.NET WebAPI C# คืออะไร

Accept: application/json → Response เป็น JSON

Content Negotiation ใน ASP.NET WebAPI C# คืออะไร

เมื่อ Response ส่งไปยัง Client ใน Format ที่ Request สังเกตว่า Header Content-Type ของ Response ถูก Set เป็นค่าที่เหมาะสม เช่น Client Request application/xml Server ส่ง Data เป็น XML และ Set Content-Type=application/xml

Content Negotiation ใน ASP.NET WebAPI C# คืออะไร

Quality Factor (q-value)

สามารถระบุ Quality Factor ได้ ในตัวอย่างด้านล่าง XML มี Quality Factor สูงกว่า JSON ดังนั้น Server ใช้ XML Formatter


Accept: application/xml;q=0.8, application/json;q=0.5

Content Negotiation ใน ASP.NET WebAPI C# คืออะไร

การกำหนด Custom Formatter


public class CsvMediaTypeFormatter : BufferedMediaTypeFormatter {
    public CsvMediaTypeFormatter() {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/csv"));
    }
    
    public override bool CanReadType(Type type) => true;
    public override bool CanWriteType(Type type) => true;
    
    public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content) {
        using var writer = new StreamWriter(writeStream, Encoding.UTF8);
        // CSV Writing Logic
        if (value is IEnumerable students) {
            writer.WriteLine("Id,Name");
            foreach (var s in students) {
                writer.WriteLine($"{s.Id},{s.Name}");
            }
        }
    }
}

// Register
config.Formatters.Add(new CsvMediaTypeFormatter());

ตอนนี้ Client สามารถ Request ได้:


Accept: text/csv

การบังคับ Format (Override Content Negotiation)


// บังคับ JSON เสมอ
config.Formatters.Remove(config.Formatters.XmlFormatter);

// บังคับ XML เสมอ  
config.Formatters.Remove(config.Formatters.JsonFormatter);

// หรือใช้ Format Parameter ใน Route
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}.{ext}",
    defaults: new { id = RouteParameter.Optional }
);
// URL: /api/student/1.json หรือ /api/student/1.xml