Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何实现指定在向RESTAPI发出get请求时接收哪些参数的功能?_C#_Sql_Rest_Asp.net Web Api - Fatal编程技术网

C# 如何实现指定在向RESTAPI发出get请求时接收哪些参数的功能?

C# 如何实现指定在向RESTAPI发出get请求时接收哪些参数的功能?,c#,sql,rest,asp.net-web-api,C#,Sql,Rest,Asp.net Web Api,因为我需要减少API的负载,所以我考虑实现一种可能性,指定您希望在请求时接收哪些属性 现在当用户向api请求获取产品时 /api/products/{id} 它们获取整个产品信息(id、名称、创建日期、UpdateDate、deleted、active等等),因此我需要从数据库中提取所有这些属性 我想要实现的是,api用户可以选择他们想要接收的属性,而不是从服务器返回产品的所有属性。URL可以如下所示: /products/{id}/props={id,name,LastUpdated} [

因为我需要减少API的负载,所以我考虑实现一种可能性,指定您希望在请求时接收哪些属性

现在当用户向api请求获取产品时

/api/products/{id}
它们获取整个产品信息(id、名称、创建日期、UpdateDate、deleted、active等等),因此我需要从数据库中提取所有这些属性

我想要实现的是,api用户可以选择他们想要接收的属性,而不是从服务器返回产品的所有属性。URL可以如下所示:

/products/{id}/props={id,name,LastUpdated}
[Flags]
public enum Props
{
    FirstName = 1,
    Surname = 2,
    Address = 4,
    Occupation = 8
}

public string GetValues(int id, Props props)
{
    var items = new Dictionary<string, string>();

    if (props == 0 || props.HasFlag(Props.FirstName))
        items.Add("FirstName", "Bob");

    if (props == 0 || props.HasFlag(Props.Surname))
        items.Add("Surname", "Smith");

    if (props == 0 || props.HasFlag(Props.Address))
        items.Add("Address", "London");

    if (props == 0 || props.HasFlag(Props.Occupation))
        items.Add("Occupation ", "Professional Tea Drinker");

    //Using Newtonsoft Json:
    return JsonConvert.SerializeObject(items);
}
GetValues(1, (Props)0)
GetValues(1, (Props)1)
GetValues(1, (Props)3)
因此,我只需要从数据库中选择id、name和LastUpdated就可以返回给API用户


如何以最智能的方式实际实现这样的功能?

编辑:现在问题已经很好地描述了

我明白了。这只有在没有模型的情况下才可能实现。(我想)

我认为JObject是一个良好的开端,它可能是这方面测试最多的库

大致应该是这样的:

/products/{id}/props={id,name,LastUpdated}
[Flags]
public enum Props
{
    FirstName = 1,
    Surname = 2,
    Address = 4,
    Occupation = 8
}

public string GetValues(int id, Props props)
{
    var items = new Dictionary<string, string>();

    if (props == 0 || props.HasFlag(Props.FirstName))
        items.Add("FirstName", "Bob");

    if (props == 0 || props.HasFlag(Props.Surname))
        items.Add("Surname", "Smith");

    if (props == 0 || props.HasFlag(Props.Address))
        items.Add("Address", "London");

    if (props == 0 || props.HasFlag(Props.Occupation))
        items.Add("Occupation ", "Professional Tea Drinker");

    //Using Newtonsoft Json:
    return JsonConvert.SerializeObject(items);
}
GetValues(1, (Props)0)
GetValues(1, (Props)1)
GetValues(1, (Props)3)
  • 解析查询字符串

  • 获取这些字段并从数据库中选择。(如果使用sql server,则可以有一个内部带有动态查询的存储过程

  • 获取结果并将其解析为json,这就是newtonsoft的用武之地

  • 返回Json

  • 是您需要的。它允许您指定需要在URL中检索的属性,然后生成对数据库的查询,该查询将仅返回这些特定属性


    基本教程(来自官方网站):

    例如,您可以执行类似的操作,但需要进行编辑以满足您的api需求

    using System;
    using System.Collections.Generic;
    using System.Dynamic;
    using System.Reflection;
    using System.Linq;
    
    public class Program
    {
    
        public class Man
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Phone { get; set; }
        }
    
        public static void Main()
        {
            var man = new Man
            {
                Id = 2,
                Name = "A Name",
                Phone = "123456789"
            };
    
            var props = "id,name";
    
            var customPropsArray = props.Split(',');
    
            Type t = man.GetType();
            PropertyInfo[] properties = t.GetProperties(
                BindingFlags.NonPublic | // Include protected and private properties
                BindingFlags.Public | // Also include public properties
                BindingFlags.Instance // Specify to retrieve non static properties
                );
    
            var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
    
            foreach (var p in properties.Where(x => customPropsArray.Contains(x.Name.ToLower())))
            {           
                dynamicObject.Add(p.Name, p.GetValue(man));
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    运用系统动力学;
    运用系统反思;
    使用System.Linq;
    公共课程
    {
    公务舱员
    {
    公共int Id{get;set;}
    公共字符串名称{get;set;}
    公用字符串电话{get;set;}
    }
    公共静态void Main()
    {
    var man=新人
    {
    Id=2,
    Name=“A Name”,
    电话=“123456789”
    };
    var props=“id,name”;
    var customPropsArray=props.Split(',');
    类型t=man.GetType();
    PropertyInfo[]properties=t.GetProperties(
    BindingFlags.NonPublic |//包括受保护和私有属性
    BindingFlags.Public |//还包括公共属性
    BindingFlags.Instance//指定以检索非静态属性
    );
    var dynamicObject=new ExpandoObject()作为IDictionary;
    foreach(properties.Where(x=>customPropsArray.Contains(x.Name.ToLower())中的var p)
    {           
    Add(p.Name,p.GetValue(man));
    }
    }
    }
    
    OData是一个好主意,但如果由于某种原因无法使用它,可以使用
    枚举来指定所需的属性,然后在API中通过
    字典将它们序列化为Json。类似如下:

    /products/{id}/props={id,name,LastUpdated}
    
    [Flags]
    public enum Props
    {
        FirstName = 1,
        Surname = 2,
        Address = 4,
        Occupation = 8
    }
    
    public string GetValues(int id, Props props)
    {
        var items = new Dictionary<string, string>();
    
        if (props == 0 || props.HasFlag(Props.FirstName))
            items.Add("FirstName", "Bob");
    
        if (props == 0 || props.HasFlag(Props.Surname))
            items.Add("Surname", "Smith");
    
        if (props == 0 || props.HasFlag(Props.Address))
            items.Add("Address", "London");
    
        if (props == 0 || props.HasFlag(Props.Occupation))
            items.Add("Occupation ", "Professional Tea Drinker");
    
        //Using Newtonsoft Json:
        return JsonConvert.SerializeObject(items);
    }
    
    GetValues(1, (Props)0)
    GetValues(1, (Props)1)
    GetValues(1, (Props)3)
    
    返回:

    {“名字”:“鲍勃”,“姓氏”:“史密斯”,“地址”:“伦敦”,“职业”:“专业饮茶者”}

    {“FirstName”:“Bob”}

    {“名字”:“鲍勃”,“姓氏”:“史密斯”}


    你可能有两个模型。模型A的属性更少,模型B的属性更多,B当然继承自A。你总是将B保存到数据库中。所以,我们的想法只是与简单的模型A进行“约定”。然后在控制器上,你可以将A作为参数传递给Constructor,在Constructor上创建B。你可以使用映射库Reflection(需要缓存),或手工绘制的地图。如果你不喜欢这个想法,请告诉我,我会尝试更好的想法。@JuanCarlos如果我有一个简单的模型和完整的模型,它会起作用,但是如果我有20种不同的属性组合的可能性,那会怎么样?而不是我必须创建20种不同的模型。我考虑实施一种策略模式每种可能都有n个,但这将是20种不同的策略。@ivan yurchenko发布的OData也是一个好主意。可能实现起来更复杂,但也更健壮。OData现在不适合实现框架。但我可以使用您的approach@Timsen谢谢你把我的建议作为答案。让我知道你是否实施了它,以及你是如何做到的。