webapi odata更新savechanges问题 - 无法连接到远程服务器

时间:2014-03-01 19:13:40

标签: asp.net-mvc azure asp.net-web-api asp.net-mvc-5

在我的mvc webapplication中,我使用webapi通过odata连接到我的数据库。

MVC WebApp和Odata WebApi都位于Azure云服务webrole端点的不同端口上。

MVC WebApp - 80
Odata WebApi - 23900

当我执行odataproxy updateobject并调用像

这样的savechanges时
odataProxy.UpdateObject(xxx);
odataProxy.SaveChanges(System.Data.Services.Client.SaveChangesOptions.PatchOnUpdate);

我在savechanges方法调用上遇到一个奇怪的异常 - 无法连接到远程服务器。

当我试图查看内部异常时,它说 - 没有连接可以作为目标机器主动拒绝它127.0.0.1:23901

因此,如果您在异常中观察到端口号,则显示为23901,显然此错误应该是因为请求应该达到23900.

仅在运行azure云解决方案时才会遇到此异常。每当我执行更新请求时,它都会因错误的端口(添加1)而失败。

另一件事是,除了这个更新对象 - > savechanges,rest all就像获取数据和添加数据一样。

2 个答案:

答案 0 :(得分:1)

FWIW,我刚遇到同样的事情。 Darn接近烦人,我真的希望它不会在生产中发生。我很惊讶没有其他人遇到这个。

创建新上下文,附加对象和调用SaveChanges的想法确实击退了我,因为它不仅实际上破坏了所有形式的测试,而且导致调试代码和生产代码根本不同

然而,我能够以另一种方式解决这个问题,方法是在它出去之前拦截请求并使用反射来戳一些内存中的私有字段以“修复”端口号。

更新:它实际上比这更容易。我们可以使用BuildingRequest事件拦截请求生成过程。它是这样的:

var context = new Context(baseUri);

context.BuildingRequest += (o, e) =>
{
    FixPort(e);
};

然后FixPort方法只需要测试端口号并构建一个新的Uri,将它附加回事件args。

[Conditional("DEBUG")]
private static void FixPort(BuildingRequestEventArgs eventArgs)
{
    int localPort = int.Parse(LOCAL_PORT);

    if (eventArgs.RequestUri.Port != localPort)
    {
        var builder = new UriBuilder(eventArgs.RequestUri);
        builder.Port = localPort;

        eventArgs.RequestUri = builder.Uri;
    }
}

以下是使用反射和SendingRequest2的原始方法,以防任何人仍感兴趣。

首先,我们创建一个上下文并将处理程序附加到SendingRequest2事件:

var context = new Context(baseUri);

context.SendingRequest2 += (o, e) =>
{
    FixPort(e.RequestMessage);
};

FixPort方法然后处理重写内部请求的URL,其中LOCAL_PORT是您期望的端口,在您的情况下为23900:

[Conditional("DEBUG")]
private static void FixPort(IODataRequestMessage requestMessage)
{
    var httpWebRequestMessage = requestMessage as HttpWebRequestMessage;
    if (httpWebRequestMessage == null) return;

    int localPort = int.Parse(LOCAL_PORT);

    if (httpWebRequestMessage.HttpWebRequest.RequestUri.Port != localPort)
    {
        var builder = new UriBuilder(requestMessage.Url);
        builder.Port = localPort;

        var uriField = typeof (HttpWebRequest).GetField("_Uri",
            BindingFlags.Instance | BindingFlags.NonPublic);
        uriField.SetValue(httpWebRequestMessage.HttpWebRequest, builder.Uri);
    }
}

答案 1 :(得分:0)

我找到了根本原因和临时解决方法。

<强>原因: 当您通过Azure计算模拟器中的某个端口:23900访问WebApi并执行更新或删除操作时,不知何故最后一个请求阻止了端口,并且由于Azure模拟器中的端口行走功能,它将跳转到下一个没有的端口可用的服务导致问题。

即使只在开发模拟器中发现此问题。

Temp解决方法: 使用其他代理附加到更新的上下文对象,然后从其他代理对象保存。

var odataProxy1 = xxx;
var obj = odataProxy1.xyz.FirstOrDefault();
obj.property1="abcd";
...//Other update assignments

var odataProxy2 = xxx;
odataProxy2.AttachTo("objEntitySet",obj);
odataProxy2.UpdateObject(obj)
odataProxy2.SaveChanges(ReplaceOrUpdate);