【问题标题】:complex object is null in Web API method using Httpclient使用 Httpclient 的 Web API 方法中的复杂对象为空
【发布时间】:2023-03-07 04:53:01
【问题描述】:

我在另一个 Web 应用程序中部署并使用了 Web API 服务。 Web API 方法采用复杂对象(列表对象)和结果也是复杂对象。

所以我为输入参数和结果模型创建了本地模型,以匹配 Web 应用程序中的 Web API 复杂对象。然后我为那个参数传递了JsonConvert.SerializeObject。但是当我在 Web API 中调试时,参数值显示为 null。

网络应用程序

 [Serializable]
    public class PreferencesInput
    {
        public string ShortName { get; set; }
        public string ShortNameDescription { get; set; }
       .....
    } 

  [Serializable]
    public class PreferencesOuput
    {
       public bool Status { get; set; }
       public string Error { get; set; }
     }
     public class HomeController : Controller
     {
           public ActionResult Index()
          {
                RunAsync().Wait();
                return View();
          }

           private static async Task RunAsync()
           {
             var inputs = new List<PreferencesInput>();
             var input = new PreferencesInput
              {
                   ShortName = "REGION",
                   ShortNameDescription = "Geographical regions",
                   OptedInFlag = true
              };
              inputs.Add(input);
              ....
              ...
              using (var client = new HttpClient())
              {
                  client.BaseAddress = new Uri("http://localhost:8585/");
                  client.DefaultRequestHeaders.Accept.Clear();
                  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                try
                {
                     HttpResponseMessage response = await client.GetAsync("preferences/updatepreferences/?id='3016523'
                      &optInInterestAreas=" + JsonConvert.SerializeObject(inputs) + 
                      "&solicitationFlag=false").ConfigureAwait(false);;

                    if (response.IsSuccessStatusCode)
                    {
                        string results = await response.Content.ReadAsStringAsync();
                        var myList = JsonConvert.DeserializeObject<List<PreferencesOuput>>(results);
                    }

网络 API

  [Route("preferences/updatepreferences")]
    [HttpGet]
    public PreferencesOuput UpdatePreferences(string id, IEnumerable<PreferencesInput> optInInterestAreas, bool solicitationFlag)
    {
       .....
    }  

唯一的区别是 Web 应用程序输入模型比 Web API 模型具有更少的参数。

我在这里做错了什么?

IEnumerable&lt;PreferencesInput&gt; optInInterestAreas 为空

更新

在发送到 Web API 调用之前,我可以看到如下所示的序列化日期,在 Web API 方法中它显示为 null,其余参数显示正确。

    [{"ShortName":"REGION","ShortNameDescription":"Geographical regions","ShortSubName":null,"Description":null,"OptedInFlag":true},
{"ShortName":"REGION","ShortNameDescription":"Asia Pacific","ShortSubName":"ASIA_PACIFIC","Description":null,"OptedInFlag":true},
{"ShortName":"REGION","ShortNameDescription":"Canada","ShortSubName":"CANADA","Description":null,"OptedInFlag":true}]

【问题讨论】:

  • 只是想知道您是否已验证您的查询字符串是否正确
  • 您的查询字符串无效。可以试试 HttpPost 吗?

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


【解决方案1】:

您可以尝试使用参数指定路线。比如:

[Route("preferences/updatepreferences/{id}/{optInInterestAreas}/{solicitationFlag:bool}")]

【讨论】:

    【解决方案2】:

    您的 optInInterestAreas 参数为空,因为在 Web API 中,parameter binding rules 指定除了“简单”参数类型(字符串、int 等)以外的任何内容都假定在正文中传递,而不是路由或你正在做的查询字符串。您可以通过在该参数上使用[FromUri] 属性或定义自定义类型转换器来使其工作,但我强烈建议更改您的API,因为它不遵循普遍接受的最佳实践。

    按照惯例,GET 被假定为无副作用,但我猜测名为 UpdatePreferences 的东西几乎肯定会更改数据。我会考虑使用不同的动词并在正文中传递更新的首选项。 POST 更好,但如果您希望它是真正的 RESTful,您应该确保 URI 唯一标识资源并使用 PUT。

    我会首先将您的输入模型更改为以下内容:

    public class PreferencesInput
    {
        public IList<InterestArea> InterestAreas { get; set; }
        public bool SolicitationFlag { get; set; }
    }
    
    public class InterestArea
    {
        public string ShortName { get; set; }
        public string ShortNameDescription { get; set; }
        ...
    }
    

    然后像这样定义您的 API 操作:

    [Route("preferences/{id}")]
    [HttpPut]
    public PreferencesOuput UpdatePreferences(string id, PreferencesInput preferences)
    {
        ...
    }
    

    如您所见,URI 现在唯一标识了事物,而动词指定了您要“做什么”;在这种情况下,用您传递的东西完全替换该 URI 中的任何内容(如果有的话)。


    旁注:

    在 MVC 方面,在 Index 操作中调用 Wait() 会在等待异步方法完成时阻塞线程。这是一个严重的僵局邀请。异步只有在你“一路”使用它时才能正常工作。在这种情况下,这非常简单 - 只需将 Index 操作更改为:

    public async Task<ActionResult> Index()
    {
        await RunAsync();
        return View();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 2022-01-26
      • 2019-01-27
      • 1970-01-01
      • 2020-01-18
      相关资源
      最近更新 更多