所以我在客户端工作,用Microsoft.OData.Client自动生成的容器拉出odata V4记录,一切都很顺利
当我想到的时候,我需要修补一条记录,没关系,我只是
_container.SaveChanges(SaveChangesOptions.None);
它开始失败
“连接尝试失败,因为连接方没有 在一段时间后正确回应,或建立连接 失败,因为连接的主机无法响应 176.34.122.158:15737"
在客户端,有些东西,仍然不知道是什么将端口从443更改为15737并将URI方案更改为plain http
Visual Studio IIS Express使用80和443以外的端口,问题只出现在我开始将客户端指向AppHarbor中的已部署服务时,所以我怀疑端口中的这种更改只发生在容器设置为带有uri的时候默认端口,但我需要做进一步的测试。
如果你,读到这篇文章了解可能导致容器中的uri发生变化的原因,我很想知道。
修复症状的脏兮兮的方法:
将标识符添加到标题时,强制uri重新进入所需的端口
public static void OnBuildingRequest(object sender, BuildingRequestEventArgs e)
{
e.Headers.Add("Authorization", "Bearer " + Properties.Settings.Default.ODataToken);
if (e.RequestUri.IsDefaultPort == false)
{
UriBuilder ub = new UriBuilder(e.RequestUri);
ub.Scheme = Uri.UriSchemeHttps;
ub.Port = 443;
e.RequestUri = ub.Uri;
}
}
是的,令牌存储在属性中我保证我会很好并稍后对其进行加密......也许:P
编辑20/7
Appharbour的支持人员非常感兴趣,并要求澄清一下,所以现在有了100%的涂鸦:
架构:
服务器:XXXX.apphb.com(SQL +实体框架(模型)+ WEB API 2 OData V4(控制器))
客户端:桌面客户端(使用Microsoft.Odata.Client的WPF,使用OData v4客户端代码生成器创建代理)
服务器< ---带令牌认证的HTTPS --->客户端
工作流程(客户端):
验证 - > GET - >补丁
在WPF页面构建期间创建容器:
public partial class PageLibrary : Page
{
Uri _uri;
Default.Container _container;
List<BookScore> _bookscores;
public PageLibrary()
{
InitializeComponent();
_uri = new Uri(Properties.Settings.Default.ServerMetadataUri); //<-- https://XXXXXX.apphb.com/Metadata/
_container = new Default.Container(_uri);
_container.BuildingRequest += (sender, e) => Authentication.OnBuildingRequest(sender, e);
}
用户请求BookScores导致:
_bookscores = (_container.BookScores).ToList();
客户端准备发送GET的请求,BuildingRequestEventArgs e指向默认端口
e.RequestUri.Port = 443
用户更改值并保存:
private void Save_Click(object sender, RoutedEventArgs e)
{
foreach (var bookscore in _bookscores)
{
_container.UpdateObject(bookscore);
}
_container.SaveChanges(SaveChangesOptions.None);
}
仍然指向正确的端口
_container.BookScores.RequestUri.Port = 443
客户端准备发送PATCH的请求,(注意参数现在如何携带不同的端口)
答案 0 :(得分:0)
根据AppHarbor的支持:
问题确实是服务器给客户端错误 URL。似乎OData / WebAPI不支持X-Forwarded-Proto 标题开箱即用。这会导致自OData客户端以来出现问题 软件不会继续使用您在设置时指定的URL OData上下文 - 它读取元数据,它将包含 错误的方案,主机名和端口
public class ForwardedProtocolHeadersHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var forwardedProtocolHeader = request.Headers.FirstOrDefault(x =>
string.Equals(x.Key, "X-Forwarded-Proto", StringComparison.InvariantCultureIgnoreCase));
if (!string.IsNullOrEmpty(forwardedProtocolHeader.Key))
{
var isHttps = string.Equals(forwardedProtocolHeader.Value.Single(), Uri.UriSchemeHttps, StringComparison.InvariantCultureIgnoreCase);
var urlBuilder = new UriBuilder(request.RequestUri)
{
Scheme = isHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp,
Port = isHttps ? 443 : 80,
};
request.RequestUri = urlBuilder.Uri;
}
return base.SendAsync(request, cancellationToken);
}
}
完整的解释:
https://support.appharbor.com/discussions/problems/83648-odata-web-api-2-patch-not-working