Microsoft.OData.Client是否更改PATCH请求的服务端口?

时间:2016-07-19 19:55:10

标签: c# rest asp.net-web-api2 odata appharbor

所以我在客户端工作,用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的请求,(注意参数现在如何携带不同的端口)

e.RequestUri.Port = 15747

1 个答案:

答案 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