【问题标题】:How to create complex .Net objects from json(javascript) in Asp.Net WebApi using RequestCommand如何使用请求命令在 Asp.Net Web Api 中从 json(javascript) 创建复杂的 .Net 对象
【发布时间】:2016-02-09 17:44:26
【问题描述】:

我已成功创建如下简单对象。

客户端js上的json如下。

{"Page":1, "Take":10, "SortOrder":"Asc", "PropName":"Id"}

在 webapi 方面,我有以下课程

public class PaginatedRequestCommand
{

    public int Page { get; set; } 

    public int Take { get; set; } 

    public string PropName { get; set; } 

    public string SortOrder { get; set; } 
}

而WebApiConfig类如下

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

    // skiped many other lines as they are not relevant

        config.ParameterBindingRules.Insert(0, typeof(PaginatedRequestCommand),
            x => x.BindWithAttribute(new FromUriAttribute()));

    }
}

所以在 Wep Api 控制器中,我有以下操作方法。

    [HttpPost]
    [HttpGet]
    public PaginatedList<PatientCategory> PatCat(PaginatedRequestCommand cmd)
    {
    //......
}

所以我在这里正确构造了 PaginatedRequestCommand 对象,并且属性 Page、Take 等是 正确可用。浏览器上的 Angularjs ajax 调用是

$http({
            method: 'GET',
            url: this.callParams.uri, // The URI
            params: this.callParams.paginationOptions, // This is where the JSON that showed earlier goes.
            headers: { 'Content-Type': 'application/Json' }
})

到目前为止,一切都很好。

现在我想传入更多参数。我想在 JSON 中包含一个数组,如下所示。

{"Page":1,"Take":10,"SortOrder":"Asc","PropName":"Id",
    "wherePredicateParams":
[{"propName":"Name","val":"s"},
 {"propName":"Description","val":"h"}
]
}

所以您看到“wherePredicateParams”是我要传递的附加对象。它是一个数组。 我需要在 WebApi 端进行哪些修改?

我尝试在 PaginatedRequestCommand 类中再添加一个属性 public string[] wherePredicateParams { get;放; } 所以全班如下。

public class PaginatedRequestCommand
{

    public int Page { get; set; } 

    public int Take { get; set; } 

    public string PropName { get; set; } 

    public string SortOrder { get; set; } 

    public string[] wherePredicateParams { get; set; }
}

这实际上是有效的,因为 PaginatedRequestCommand 对象的属性 wherePredicateParams 由 api 在上述控制器的操作方法中创建 正在为我提供{"propName":"Name","val":"s"}{"propName":"Description","val":"h"}。但问题是我必须自己解析并使用它。有没有更好的办法。

然后我尝试将 string[] 更改为 whereParam[] 并定义了一个类

public class whereParam 
{
    public string propName { get; set; }
    public string val { get; set; }
}

所以你看到 propName 和 val 是空的?我错过了什么?

【问题讨论】:

    标签: json asp.net-web-api


    【解决方案1】:

    经过一番挣扎,我找到了答案。问题不在 webApi 方面。它在客户端。我正在使用 AngularJS 进行 ajax 调用。所以这就是问题所在。我在这里描述一下。

    请注意,我在粗略调查期间更改了类名,因此类名 PaginatedRequestCommand 现在将是 PaginatedRequest。同样会有一些其他的变化。为了避免混淆,我将再次在这里发布所有细节。

    以前是

    $http({
                method: 'GET',
                url: this.callParams.uri,
                params: this.callParams.paginationOptions,
                headers: { 'Content-Type': 'application/Json' }
    })
    

    您会看到 this.callParams.paginationOptions。那个 javascript 对象看起来像这样。

    {"Page":1,"Take":10,"SortOrder":"Asc","PropName":"Id","whereParams": 
    [{"FilterPropName":"Name","FilterPropValue":"jk"}]}
    

    this.callParams.uri 会是这样的。

    '/api/PatientCategoryApi/PatCat'
    

    这里PatientCategoryApi是WebApi控制器,PatCat是WebApi端的action方法。需要具有以下签名的操作方法。

        [HttpPost]
        [HttpGet]
        public PaginatedList<PatientCategory> PatCat(PaginatedRequest rqst)
    

    PaginatedRequest类如下。

    public class PaginatedRequest
    {
        public int Page { get; set; } // Page Index
        public int Take { get; set; } // Page Size
        public string PropName { get; set; } // Property Name for sorting.
        public string SortOrder { get; set; }  // Sort Direction Asc or Desc
        public List<WhereParam> whereParams { get; set; }
    }
    

    WhereParam类如下

    public class WhereParam
    {
        public string FilterPropName { get; set; }
        public string FilterPropValue { get; set; }
    }
    

    在webApiConfig中配置参数绑定规则如下。

    config.ParameterBindingRules.Insert(0, typeof(PaginatedRequest),
        x => x.BindWithAttribute(new FromUriAttribute()));
    

    这就是全部。如果我使用 JQuery,这将起作用。但是对于 AngularJS,序列化是不同的。 所以诀窍是添加

    paramSerializer: '$httpParamSerializerJQLike',
    

    到 ajax 调用。我在这个问题中找到了AngularJS GET ajax call with Array parameters。 所以整个调用现在看起来如下所示。

    $http({
                method: 'GET',
                url: this.callParams.uri,
                paramSerializer: '$httpParamSerializerJQLike',
                params: this.callParams.paginationOptions,
                headers: { 'Content-Type': 'application/Json' }
    })
    

    现在这确保了序列化将是 WebApi 理解的方式。并且 WebApi 端的绑定正确发生。

    如果您愿意,您还可以如下更改操作方法签名,将 List 属性分离为一个参数。在这种情况下,绑定不再是一个复杂的对象,而是一个简单的对象和一个数组(或列表)。

    [HttpPost]
    [HttpGet]
    public PaginatedList<PatientCategory> PatCat(PaginatedRequest rqst, 
    List<WhereParam> whereParams){...}
    

    在这种情况下,PaginatedRequest 不会将 WhereParam 列表作为属性。

    public class PaginatedRequest
    {
        public int Page { get; set; } // Page Index
        public int Take { get; set; } // Page Size
        public string PropName { get; set; } // Property Name for sorting.
        public string SortOrder { get; set; }  // Sort Direction Asc or Desc
        // You dont want this here in this approach.
        //public List<WhereParam> whereParams { get; set; }
    }
    

    并且在 webApiConfig 类中你需要额外添加以下内容。

            config.ParameterBindingRules.Insert(0, typeof(List<WhereParam>),
                x => x.BindWithAttribute(new FromUriAttribute()));
    

    并且客户端不需要进行其他更改。这应该有效。 总的来说,无论如何,关键是我提到的,

    paramSerializer: '$httpParamSerializerJQLike',

    【讨论】:

      【解决方案2】:

      属性wherePredicateParamsstring[] 而不是whereParam[] 所以这使得序列化程序不序列化这个属性,但我建议你使用Json.NET 你可以在这里得到它http://www.newtonsoft.com/json,这个库允许您在将 json 模式映射到类/类型的属性上使用属性。

      你可以做类似例子的事情:

      public class WhereParam 
      {
          [JsonProperty("propName")]
          public string PropName { get; set; }
          [JsonProperty("val")]
          public string Val { get; set; }
      }
      

      【讨论】:

        猜你喜欢
        • 2022-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多