首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASMX Web Service 實現多型參數傳遞:XmlIncludeAttribute 完整應用指南

     編輯:ASP.NET 基礎

問題背景

ASMX Web Service 方法參數預設為具體型別。若需傳遞**繼承階層物件** (基底類別參數接收衍生類別實例),需讓 XML 序列化器識別衍生型別,否則反序列化時只會產生基底類別實例,衍生屬性遺失。

解決方案:XmlIncludeAttribute

在 Web 方法或基底類別標註 `[XmlInclude(typeof(DerivedType))]`,告知 `XmlSerializer` 可能出現的衍生型別。

完整實作範例

1. 定義型別階層

public abstract class Vehicle
{
    public string LicenseNumber { get; set; }
    public DateTime MakeTime { get; set; }
}

public class Car : Vehicle
{
    public int DoorCount { get; set; }
    public string EngineType { get; set; }
}

public class Truck : Vehicle
{
    public double LoadCapacityTons { get; set; }
    public int AxleCount { get; set; }
}

2. Web 方法標註 XmlInclude

[WebService(Namespace = "https://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class VehicleService : System.Web.Services.WebService
{
    [WebMethod]
    [XmlInclude(typeof(Car))]
    [XmlInclude(typeof(Truck))]
    public string RegisterVehicle(Vehicle vehicle)
    {
        if (vehicle is Car car)
            return $"Car registered: {car.LicenseNumber}, Doors: {car.DoorCount}";
        if (vehicle is Truck truck)
            return $"Truck registered: {truck.LicenseNumber}, Capacity: {truck.LoadCapacityTons}t";
        return $"Vehicle registered: {vehicle.LicenseNumber}";
    }
}

3. 產生的 WSDL 片段

<xs:complexType name="Vehicle">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" name="LicenseNumber" type="xs:string" />
        <xs:element minOccurs="1" maxOccurs="1" name="MakeTime" type="xs:dateTime" />
    </xs:sequence>
</xs:complexType>

<xs:complexType name="Car">
    <xs:complexContent mixed="false">
        <xs:extension base="tns:Vehicle">
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" name="DoorCount" type="xs:int" />
                <xs:element minOccurs="0" maxOccurs="1" name="EngineType" type="xs:string" />
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

關鍵:`` 明確描述繼承關係。

4. 客戶端 Proxy 產生的型別定義

[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Truck))]
[XmlType(Namespace="https://tempuri.org/")]
public abstract partial class Vehicle { ... }

public partial class Car : Vehicle { ... }
public partial class Truck : Vehicle { ... }

5. 客戶端呼叫代碼

var client = new VehicleServiceSoapClient();

var car = new Car 
{ 
    LicenseNumber = "ABC-1234", 
    MakeTime = DateTime.Now, 
    DoorCount = 4, 
    EngineType = "Hybrid" 
};
string result = client.RegisterVehicle(car); // 正確序列化 Car 型別

var truck = new Truck
{
    LicenseNumber = "TRK-999",
    MakeTime = DateTime.Now,
    LoadCapacityTons = 15.5,
    AxleCount = 3
};
result = client.RegisterVehicle(truck); // 正確序列化 Truck 型別

進階用法:在基底類別定義 XmlInclude (集中管理)

[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Truck))]
[XmlInclude(typeof(Motorcycle))]
public abstract class Vehicle { ... }

優點:所有使用 `Vehicle` 參數的 Web 方法自動支援多型,無需重複標註。缺點:基底類別耦合所有衍生類別,違反開放封閉原則。

限制與替代方案

限制說明替代方案
僅支援已知衍生型別需預先在 XmlInclude 列出,動態載入外掛型別不支援改用 WCF `KnownTypeAttribute` / `ServiceKnownType`,支援動態型別解析器
序列化為 XML,體積較大不適合高頻、大量資料傳輸WCF `NetTcpBinding` / `binaryMessageEncoding`、gRPC Protobuf
ASMX 屬舊技術.NET Framework 4.8 為最後版本,不再新增功能遷移至 ASP.NET Core Web API / gRPC,原生支援多型 (JSON `$type` / Protobuf)
非 .NET 客戶端難以處理需手動解析 XML 中的 xsi:typeRESTful API 使用 JSON + 自訂型別判別欄位 (如 "vehicleType": "Car")

現代化多型 API 設計模式 (ASP.NET Core)

// 使用 JsonPolymorphism (System.Text.Json 7.0+)
[JsonDerivedType(typeof(Car), "car")]
[JsonDerivedType(typeof(Truck), "truck")]
public abstract class Vehicle { ... }

[HttpPost]
public ActionResult Register([FromBody] Vehicle vehicle) 
{
    return vehicle switch
    {
        Car c => Ok($"Car: {c.DoorCount} doors"),
        Truck t => Ok($"Truck: {t.LoadCapacityTons}t"),
        _ => BadRequest()
    };
}

結語

`XmlIncludeAttribute` 是 ASMX 時代實現 Web Service 多型的標準機制,透過在 WSDL 中明確描述型別繼承關係,使客戶端 Proxy 正確產生衍生類別並序列化。但受限於 XML 序列化效能、ASMX 技術淘汰、跨平台互通性差,**新專案請直接採用 ASP.NET Core Web API + System.Text.Json 多型序列化**,獲得更優雅、高效能、跨平台的解決方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved