如何使用 C# 将复杂类对象传递给 Web API

本文关键字:Web API 对象 何使用 复杂 | 更新日期: 2023-09-27 18:33:06

我需要将复杂或List<>类对象传递给C#中的Web API,而无需AJAX或jQuery。这是我用于 API 和控制器的代码。

网页应用接口:

[AcceptVerbs("GET", "POST")]
[HttpGet]
public void WriteBusinessObjectApiFromObj(int Pa1, string Pa2, object item)
        {
            // To Do In Function 
        }

控制器:

 public void WriteBusinessObjectApi(object obj)
        {

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:8080/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                var apiUrl = "api/WriteBusinessObjectApiFromObj?Pa1=1&Pa2=2";
                var response = client.PostAsJsonAsync(apiUrl, obj).Result;
                client.Dispose();
                if (response.IsSuccessStatusCode)
                {
                }
            }
        }

我尝试调用 API,但无法向其发送对象。

我尝试发送的这个对象如下:

从此函数返回的对象列表:

public List<Product> GetProductsObj()
        {
            var products = new List<Product>
            {
                new Product()
                {
                    Id = 4,
                    Name = "product 4",
                    SupProducts = new List<SupProduct>
                    {
                        new SupProduct()
                        {
                            Id = 41,
                            Name = "Sup 41"
                        },
                        new SupProduct()
                        {
                            Id = 42,
                            Name = "Sup 42"
                        },
                        new SupProduct()
                        {
                            Id = 43,
                            Name = "Sup 43"
                        }
                    }
                },
                new Product()
                {
                    Id = 5,
                    Name = "product 5",
                    SupProducts = new List<SupProduct>
                    {
                        new SupProduct()
                        {
                            Id = 51,
                            Name = "Sup 51"
                        },
                        new SupProduct()
                        {
                            Id = 52,
                            Name = "Sup 52"
                        },
                        new SupProduct()
                        {
                            Id = 53,
                            Name = "Sup 53"
                        }
                    }
                },
                new Product()
                {
                    Id = 6,
                    Name = "product 6",
                    SupProducts = new List<SupProduct>
                    {
                        new SupProduct()
                        {
                            Id = 71,
                            Name = "Sup 71"
                        },
                        new SupProduct()
                        {
                            Id = 72,
                            Name = "Sup 72"
                        },
                        new SupProduct()
                        {
                            Id = 73,
                            Name = "Sup 73"
                        }
                    }
                }
            };
            return products;
        }

如何使用 C# 将复杂类对象传递给 Web API

绑定

器可能会变得混乱并试图错误地混合 FromBody 和 FromURI,因此请尝试将所有参数包装在一个对象中。 无论如何,这是一个更好的模式,因为您明确说明了发出"请求"的内容。 另请注意,在下面我指定对象类型,而不仅仅是说"对象"。 最好明确一点,反正你都知道两边的类型!

public class WriteBusinessObjectApiFromObjRequest
{
    public int Pa1 { get; set; }
    public string Pa2 { get; set; }
    public List<Product> Item { get; set; } // change to your Type
}
[AcceptVerbs("GET", "POST")]
[HttpGet]
public void WriteBusinessObjectApiFromObj(WriteBusinessObjectApiFromObjRequest request)
{
    // To Do In Function 
}
var apiUrl = "api/WriteBusinessObjectApiFromObj";
var response = client.PostAsJsonAsync(
     apiUrl, 
     new WriteBusinessObjectApiFromObj { Pa1 = 1, Pa2 = "2", Item = obj })
     .Result;

下面是如何使用参数绑定的很酷的概述,不涉及任何技术细节。或者,下面是对 Web API 参数绑定<</p>

div class="answers">模型的更深入的探索

public class Employee
{
    [Required]
    public string EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int EmployeeRollNum { get; set; }
    public EmployeeAddress EmployeeAddr { get; set; }
    public List<EmployeeAddress> AllEmployeeAddr { get; set; }
}
public class EmployeeAddress
{
    //[Required]
    public string EmployeeAddressId { get; set; }
    public string EmployeeAddressName { get; set; }
    public List<int> AllNum { get; set; }
}

在 Web API 服务器中:

    [HttpGet]
    public object Get([FromUri]Employee employee)
    {
        if (employee != null && ModelState.IsValid)
        {
            // Do something with the product (not shown). 
            return employee;
        }

        return employee;
    }

在 Web API 客户端中:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace WebApiConsoleApplication1
{
    public static class UrlHelpers
    {
        /// <summary>
        /// To the query string. http://ole.michelsen.dk/blog/serialize-object-into-a-query-string-with-reflection.html 
        /// </summary>
        /// <param name="request"> The request. </param>
        /// <param name="separator"> The separator. </param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException"> request </exception>
        public static string ToQueryString(this object request, string innerPropertyName = null, string separator = ",")
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }
            StringBuilder propertyQuery = new StringBuilder();
            // Get all primitive properties on the object 
            var properties = request.GetType().GetProperties()
                .Where(x => x.CanRead)
                .Where(x => x.GetValue(request, null) != null)
                .Where(x => !x.PropertyType.IsClass || (x.PropertyType.IsClass && x.PropertyType.FullName == "System.String"))
                .ToDictionary(x => x.Name, x => x.GetValue(request, null));
            foreach (KeyValuePair<string, object> kvp in properties)
            {
                if (string.IsNullOrEmpty(innerPropertyName))
                {
                    propertyQuery.AppendFormat("{0}={1}", Uri.EscapeDataString(kvp.Key), Uri.EscapeDataString(kvp.Value.ToString()));
                }
                else
                {
                    propertyQuery.AppendFormat("{0}.{1}={2}", Uri.EscapeDataString(innerPropertyName), Uri.EscapeDataString(kvp.Key), Uri.EscapeDataString(kvp.Value.ToString()));
                }
                propertyQuery.AppendFormat("&");
            }
            var innerClass = request.GetType().GetProperties()
                .Where(x => x.CanRead)
                .Where(x => x.GetValue(request, null) != null && x.PropertyType.IsClass && x.PropertyType.FullName != "System.String" && !(x.GetValue(request, null) is IEnumerable))
                .ToDictionary(x => x.Name, x => x.GetValue(request, null));
            // Get names for all IEnumerable properties (excl. string) 
            var propertyCollectionNames = request.GetType().GetProperties()
                .Where(x => x.CanRead)
                .Where(x => x.GetValue(request, null) != null)
                .ToDictionary(x => x.Name, x => x.GetValue(request, null))
                .Where(x => !(x.Value is string) && x.Value is IEnumerable)
                .ToDictionary(x => x.Key, x => x.Value);
            // Concat all IEnumerable properties into a comma separated string 
            foreach (var kvp in propertyCollectionNames)
            {
                var valueType = kvp.Value.GetType();
                var valueElemType = valueType.IsGenericType
                                        ? valueType.GetGenericArguments()[0]
                                        : valueType.GetElementType();
                if (valueElemType.IsPrimitive || valueElemType == typeof(string)) // List of primitive value type or string
                {
                    var enumerable = kvp.Value as IEnumerable;
                    int count = 0;
                    foreach (object obj in enumerable)
                    {
                        if (string.IsNullOrEmpty(innerPropertyName))
                        {
                            propertyQuery.AppendFormat("{0}[{1}]={2}", Uri.EscapeDataString(kvp.Key), count, Uri.EscapeDataString(obj.ToString()));
                        }
                        else
                        {
                            propertyQuery.AppendFormat("{0}.{1}[{2}]={3}", Uri.EscapeDataString(innerPropertyName), Uri.EscapeDataString(kvp.Key), count, Uri.EscapeDataString(obj.ToString()));
                        }
                        count++;
                        propertyQuery.AppendFormat("&");
                    }
                }
                else if (valueElemType.IsClass) // list of class Objects
                {
                    int count = 0;
                    foreach (var className in kvp.Value as IEnumerable)
                    {
                        string queryKey = string.Format("{0}[{1}]", kvp.Key, count);
                        propertyQuery.AppendFormat(ToQueryString(className, queryKey));
                        count++;
                    }
                }
            }
            foreach (var className in innerClass)
            {
                propertyQuery.AppendFormat(ToQueryString(className.Value, className.Key));
            }
            return propertyQuery.ToString();
        }
    }
    public class Employee
    {
        public string EmployeeId { get; set; }
        public string EmployeeName { get; set; }
        public int EmployeeRollNum { get; set; }
        public EmployeeAddress EmployeeAddr { get; set; }
        public List<EmployeeAddress> AllEmployeeAddr { get; set; }
    }
    public class EmployeeAddress
    {
        //[Required]
        public string EmployeeAddressId { get; set; }
        public string EmployeeAddressName { get; set; }
        public List<int> AllNum { get; set; }
    }
    internal class Program
    {
        private static void Main()
        {
            RunAsync().Wait();
            Console.WriteLine("Completed");
            Console.ReadLine();
        }
        private static async Task RunAsync()
        {
            try
            {
                using (var client = new HttpClient())
                {
                    client.BaseAddress = new Uri(ConfigurationManager.AppSettings.Get("HostURL"));
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(ConfigurationManager.AppSettings.Get("AcceptType")));
                    HttpResponseMessage response = await client.GetAsync("api/Values/1");
                    if (response.IsSuccessStatusCode)
                    {
                        string val = await response.Content.ReadAsAsync<string>();
                        Console.WriteLine("{0}'t", val);
                    }
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(ConfigurationManager.AppSettings.Get("AcceptType")));
                    //client.DefaultRequestHeaders.Add()
                    // HTTP GET
                    Employee emp = new Employee();
                    emp.EmployeeId = "sri1";
                    emp.AllEmployeeAddr = new List<EmployeeAddress>();
                    EmployeeAddress lstemployeeAddr = new EmployeeAddress();
                    lstemployeeAddr.EmployeeAddressId = "Address1";
                    lstemployeeAddr.AllNum = new List<int>();
                    lstemployeeAddr.AllNum.Add(1);
                    lstemployeeAddr.AllNum.Add(2);
                    lstemployeeAddr.AllNum.Add(3);
                    emp.AllEmployeeAddr.Add(lstemployeeAddr);
                    lstemployeeAddr = new EmployeeAddress();
                    lstemployeeAddr.EmployeeAddressId = "Address2";
                    lstemployeeAddr.AllNum = new List<int>();
                    lstemployeeAddr.AllNum.Add(24);
                    lstemployeeAddr.AllNum.Add(56);
                    emp.AllEmployeeAddr.Add(lstemployeeAddr);
                    EmployeeAddress innerEmployeeAddr = new EmployeeAddress();
                    innerEmployeeAddr.EmployeeAddressId = "Addr3";
                    innerEmployeeAddr.AllNum = new List<int>();
                    innerEmployeeAddr.AllNum.Add(5);
                    innerEmployeeAddr.AllNum.Add(6);
                    emp.EmployeeAddr = innerEmployeeAddr;
                    string query = emp.ToQueryString();
                    response = await client.GetAsync("api/Values?" + query);
                    if (response.IsSuccessStatusCode)
                    {
                        Employee product = await response.Content.ReadAsAsync<Employee>();
                        Console.WriteLine("{0}'t{1}'t", product.EmployeeId, product.EmployeeName);
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
    }
}