【问题标题】:404 error when posting to Web API 2 action using HttpClient使用 HttpClient 发布到 Web API 2 操作时出现 404 错误
【发布时间】:2018-05-18 10:34:42
【问题描述】:

好的,这里有很多事情要做,所以我会尽量让我的问题和示例保持简单。考虑到这一点,请询问您是否需要任何其他信息或澄清任何事情。

代码

我有一个 Web API 2 项目,其中包含许多控制器和操作。我遇到问题的特定操作在 ContactController 中定义如下:

[HttpPost]
public MyModel GetSomething(System.Nullable<System.Guid> uid)
{
    return GetMyModel(uid);
}

以防万一,我的路由设置如下:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = RouteParameter.Optional }
);

现在我有另一个项目需要调用上述操作。为了调用 Web API,我使用了HttpClient。请注意,我还有许多其他操作调用正常,因此这不是连接问题。

我用来调用Web API方法的代码如下:

using (HttpClient client = GetClient())
{
    var obj = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("uid", someGuid.ToString()) };
    var response = client.PostAsync(path, new FormUrlEncodedContent(obj)).Result;

    return response.Content.ReadAsAsync<T>().Result;
}

在这种情况下,path 基本上是:

localhost:12345/api/contact/getsomething

问题

PostAsync 调用 Result(即上述代码中的 response)给出了以下消息:

{StatusCode:404,ReasonPhrase:“未找到”,版本:1.1,内容:System.Net.Http.StreamContent,标头: { Pragma:无缓存 X-SourceFiles: =?UTF-8?B?QzpcRGV2ZWxvcG1lbnRcUHJvamVjdHNcTGltYVxMaW1hIHYzXERFVlxMaW1hRGF0YVNlcnZpY2VcYXBpXHVzZXJhY2Nlc3NcZ2V0bW9kdWxlc2FjY2Vzcw==?= 缓存控制:无缓存 日期:格林威治标准时间 2018 年 5 月 18 日星期五 10:25:49 服务器:Microsoft-IIS/10.0 X-AspNet-版本:4.0.30319 X-Powered-By: ASP.NET 内容长度:222 内容类型:应用程序/json;字符集=utf-8 过期:-1 }}

如果我在 aciton 中放置一个断点,那么它就不会触发。但是,我觉得奇怪的是,当我调用它时,Visual Studio (2018) 告诉我特定操作对该特定操作有一个“失败的请求”。这么清楚它必须知道我要调用哪个方法?

此时我已经没有关于如何进一步调试的想法了。我在这里做错了什么?

【问题讨论】:

  • 不相关但不阻止与.Result 的异步。搞清楚 404 问题后,你可能会陷入僵局。
  • @Crowcoder:我会调查,但我实际上并不希望它是异步的
  • 然后使用同步 API,如 HttpWebRequest 或其他。

标签: c# asp.net-web-api2 dotnet-httpclient


【解决方案1】:

在这种情况下,您可以使用与获取和发布相同的端点。

所以你可能需要:

[HttpGet]
public IActionResult Get(System.Nullable<System.Guid> uid)
{
    return GetMyModel(uid); //make sure you got it, oterhwise return a NotFound()
}

[HttpPost]
public IActionResult Post(InputModel model)
{
    _service.doMagicStuff();
    return Ok();
}

干杯!

【讨论】:

  • 顺便说一句;注入你的 HttpClient 而不是“使用”,httpclient 应该是一个单例,干杯! (看看.net core 2.1(httpclientfactory)
  • 感谢您的评论,我会看看的。但是关于回答,我想使用 post 方法来满足我的要求。
  • 什么意思?它到位了吗? (更改方法名称):Post
  • 我的意思是我想保持我的控制器操作与我的问题中的相同(除非我有充分的理由改变它)。所以我想要一个名为 GetMyModel 的 POST 操作,它采用 Guid 值。
  • guid 解析出错了吗?如果您将其作为字符串尝试会发生什么?
【解决方案2】:

不确定但错误可能是因为您正在传递键值对

var obj = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("uid", someGuid.ToString()) };
var response = client.PostAsync(path, new FormUrlEncodedContent(obj)).Result;

而不是仅公会,即仅函数期望的字符串值,因此它将是

var response = client.PostAsync(path, new FormUrlEncodedContent(someGuid.ToString())).Result;

方法应该是

[HttpPost]
public MyModel GetSomething(string uid)
{
    return GetMyModel(Guid.Parse( uid));
}

【讨论】:

  • 嗯...我可以试一试。但是如果我想要 2 个参数 (Guid uid, string somethingElse) 怎么办呢?
  • @musefan - 然后你需要创建类并传递值,这就是我从我的角度代码调用 api 时所做的,我传递具有所有属性的类对象,就像你的情况一样应该有两个属性的类
  • 是的,我曾考虑过使用模型...但我希望这是最后的手段,因为如果我能提供帮助,我不希望为每个单独的操作使用自定义类
  • @musefan - 最好有模型专门用于帖子的情况,并且当您的方法参数增加超过 2 时
【解决方案3】:

您正在发送带有 FormUrlEncodedContent 的 guid,但请求的内容类型是 application/json。 我建议你将它作为这样的 json 发送

using (HttpClient client = GetClient())
{
    var obj = new { uid = someGuid.ToString()) };
    var json = JsonConvert.SerializeObject(obj);
    var content = new StringContent(json, Encoding.UTF8, "application/json");
    var result = client.PostAsync(path, content).Result;

    return response.Content.ReadAsAsync<T>().Result;
}

然后在api控制器中,使用FromBody属性声明参数是从请求体中读取的

[HttpPost]
public MyModel GetSomething([FromBody]RequestModel model)
{
    return GetMyModel(model.uid);
}

public class RequestModel
{
    public System.Nullable<System.Guid> uid { get; set; }
}

此外,如果您在联系人控制器中只有一个 Post 方法,则 url localhost:12345/api/contact 就足够了

【讨论】:

  • 我必须将参数更改为RequestModel类吗?我真的想让它只与Guid 一起工作。另外,当我尝试你的建议时,我遇到了同样的问题......
  • @musefan 如果您希望主体是基于键值的,那么您需要将参数包装在模型中。您是否也将路径/网址更改为仅 POST localhost:12345/api/contact
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-19
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 2018-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多