【问题标题】:Accessing a webservice running as a virtual directory, with HttpClient使用 HttpClient 访问作为虚拟目录运行的 Web 服务
【发布时间】:2014-06-09 15:33:53
【问题描述】:

我们有一个 MVC Web 应用程序,它使用 System.Net.HttpClient.PostAsJsonAsync 对 Web 服务进行服务器端调用。

当 web 服务在 IIS 中作为根站点运行时,这可以正常工作。但是当我们在 IIS 中将其配置为虚拟目录时,System.Net.HttpClient.PostAsJsonAsync 会发布到错误的 URL。

using (var client = new HttpClient())
{
      var webServiceUrl = ConfigurationManager.AppSettings["WebServiceUrl"];
      if (webServiceUrl == null)
           throw new Exception("WebServiceUrl not set in web.config");

      client.BaseAddress = new Uri(webServiceUrl);
      client.DefaultRequestHeaders.Accept.Clear();
      client.DefaultRequestHeaders.Accept.Add(
      new MediaTypeWithQualityHeaderValue("application/json"));

      HttpResponseMessage response = 
           await client.PostAsJsonAsync("api/Authentication", loginModel);

      if (response.IsSuccessStatusCode)
           ...

当我在调试器中跟踪它时,我看到 webServiceUrl 设置为域+虚拟目录(即http://mydomain.com/myvirtualdirectory)。

然后当我收到响应时,它有一个 StatusCode 404,“未找到”。事情是这样的——响应对象包含 RequestMessage,请求中的 URL 不包含虚拟目录。

我们从“http://mydomain.com/myvirtualdirectory”的 BaseAddress 和“api/Authentication”的 RequestUri 开始,我在 RequestMessage 中看到的是“http://mydomain.com/api/Authentication”。虚拟目录已被剥离。

问题是,为什么?

【问题讨论】:

  • 在回答之前阅读问题。

标签: c# asp.net-mvc


【解决方案1】:

这里看起来很清楚:WebClient 不知道虚拟目录。从客户端的角度来看,虚拟目录只是另一个文件夹。所以而不是

await client.PostAsJsonAsync("api/Authentication", loginModel);

你应该使用:

await client.PostAsJsonAsync("myvirtualdirectory/api/Authentication", loginModel);

【讨论】:

  • 如果我不使用 BaseAddress,而是将完整的 URI 传递到 PostAsJsonAsync(),一切正常。很明显,HttpClient.BaseAddress 命名错误——它被用作站点域名,而不是站点的基地址。
  • 没有错名。从客户端的角度来看,mysite.com 是一个基地址,而mysite.com/myvirtualdirectory 只是mysite.com 的一个文件夹。
  • 当我将 HttpClient.BaseAddress 设置为 mysite.com/myvirtualdirectory 时,我告诉 HttpClient 那是我的基地址。或者我想,从命名和文档来看。奇怪的是,如果它以“/”结尾,它似乎只将其视为基地址。这根本没有意义。
  • 我不认为WebClient 是密封的。欢迎您更改其行为方式。
  • 我刚刚遇到了类似的问题。我的 baseAddress 类似于:myservice.com/myvirtualdirectory。对我来说,诀窍是在末尾简单地添加一个斜杠,将其变为:myservice.com/myvirtualdirectory 问题已解决。其他人可以确认吗?
【解决方案2】:

您可能希望BaseUri 以斜线结尾。

想象一下,您的浏览器在http://example.com/myvirtualdirectory 上,并且有一个指向api 的链接。 它会去哪里?

http://example.com/api

想象一下,有一个指向api/Authentication 的链接。 它指向哪里? 致http://example.com/api/Authentication

所以你明白为什么会这样。 知道myvirtualdirectory是一个目录,但它在机器上看起来不像。

【讨论】:

  • 我不希望任何东西依赖于 web.config 设置中的路径或 URL 是否以斜杠结尾。这是一个正在发生的配置错误。不过,如果我添加斜线,我会得到我想要的行为 - Post 中的路径被附加到 BaseAddress。
  • @JeffDege 我能告诉你什么?这就是它的指定方式,对我来说很有意义。您的输入不正确。修理它。或者,在 web.config 中定义 URL 前缀。我不明白你为什么需要 BaseUri 。只需附加字符串。应用启动时,添加assert(myBaseUri.StartsWith("/")),错误会立即提示。
  • 从另一条评论中我可以看出你还没有理解 BaseAddress 的工作原理。它的工作原理与浏览器完全相同。它不仅仅是简单的字符串连接。
  • 很明显我不明白 BaseAddress 是如何工作的。我并不表示 BaseAddress 的文档或它的设计失败。在这种情况下,我会说两者。我找不到讨论这些问题的 BaseAddress 文档。至于设计,除了网站的根 URL 之外,BaseAddress 应该代表什么?并且基于目录分隔符的存在或不存在而改变行为显然违反了最小惊讶原则。
  • 不过,抱怨 MS 的设计或文档问题是徒劳的。感谢大家帮助我们找到解决方案。
猜你喜欢
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多