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

时间:2014-12-03 10:56:34

标签: c# asp.net-mvc-4 asp.net-web-api

我需要传递复数或List<>类对象为C#中的Web API,没有AJAX或jQuery。这是我用于API和控制器的代码。

Web 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;
        }

2 个答案:

答案 0 :(得分:1)

可能是活页夹混乱并试图错误地混合FromBody和FromURI,所以尝试将所有参数包装在对象中。无论如何,这是一个更好的模式,因为您明确说明了什么是一个&#34;请求&#34;。另请注意,在下面我指定对象类型而不是仅仅说&#34; object&#34;。更明确的是,无论如何你都知道双方的类型!

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;

这是cool overview of how to use parameter binding,不会涉及任何技术细节。或者,这是much more in depth exploration of Web API parameter binding

答案 1 :(得分:0)

型号:

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)
            {
            }
        }
    }
}