C# 使用Httpclient的Web API方法中的复杂对象为null

C# 使用Httpclient的Web API方法中的复杂对象为null,c#,asp.net-mvc,asp.net-web-api,C#,Asp.net Mvc,Asp.net Web Api,我在另一个Web应用程序中部署并使用了Web API服务。WebAPI方法接受复杂对象(列表对象),结果也是复杂对象 所以我为输入参数和结果模型创建了本地模型,以匹配Web应用程序中的Web API复杂对象。然后我为该参数传递了JsonConvert.SerializeObject。但当我在Web API中调试时,该参数值显示为null Web应用程序 您可以尝试使用参数指定管线。比如: [Route("preferences/updatepreferences/{id}/{optInInter

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

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

Web应用程序
您可以尝试使用参数指定管线。比如:

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

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

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

您的
optionInterestAreas
参数为空,因为在Web API中,指定除了“简单”参数类型(字符串、int等)之外的任何内容都假定在正文中传递,而不是您正在执行的路由或查询字符串。您可以通过在该参数上使用
[FromUri]
属性或定义自定义类型转换器来实现这一点,但我强烈建议您更改API,因为它没有遵循公认的最佳实践

按照惯例,
GET
被认为是没有副作用的,但我猜一种叫做UpdatePreferences的东西几乎肯定会改变数据。我会考虑使用一个不同的动词,并在身体中传递更新的首选项。code>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; }
    ...
}
[Route("preferences/{id}")]
[HttpPut]
public PreferencesOuput UpdatePreferences(string id, PreferencesInput preferences)
{
    ...
}
正如您所看到的,URI现在唯一地标识了事物,动词指定了您想要“做什么”;在本例中,用您正在传递的内容完全替换该URI上的内容(如果有)


旁注:

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

public async Task<ActionResult> Index()
{
    await RunAsync();
    return View();
}
公共异步任务索引()
{
等待RunAsync();
返回视图();
}

您的
optionInterestAreas
参数为空,因为在Web API中,指定除了“简单”参数类型(字符串、int等)之外的任何内容都假定在正文中传递,而不是像您这样传递路由或查询字符串。您可以通过在该参数上使用
[FromUri]
属性或定义自定义类型转换器来实现这一点,但我强烈建议您更改API,因为它没有遵循公认的最佳实践

按照惯例,
GET
被认为是没有副作用的,但我猜一种叫做UpdatePreferences的东西几乎肯定会改变数据。我会考虑使用一个不同的动词,并在身体中传递更新的首选项。code>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; }
    ...
}
[Route("preferences/{id}")]
[HttpPut]
public PreferencesOuput UpdatePreferences(string id, PreferencesInput preferences)
{
    ...
}
正如您所看到的,URI现在唯一地标识了事物,动词指定了您想要“做什么”;在本例中,用您正在传递的内容完全替换该URI上的内容(如果有)


旁注:

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

public async Task<ActionResult> Index()
{
    await RunAsync();
    return View();
}
公共异步任务索引()
{
等待RunAsync();
返回视图();
}

只是想知道您是否验证了查询字符串是否正确您的查询字符串无效。你能试试HttpPost吗?只是想知道你是否已经验证了你的查询字符串是正确的,你的查询字符串是无效的。你能试试HttpPost吗?