ASP .Net - Entity Framework - MobileAppService - 将实体对象推送到后端时出错

ASP .Net - Entity Framework - MobileAppService - Error in pushing entity object to backend

我正在使用 Xamarin 中的离线同步功能在我的移动应用程序和托管在 Azure 上的 MobileAppService 之间同步数据。 我使用了 Entity Framework (V6.1.3),使用 visual studio 包管理器使用代码优先迁移创建了我的数据库。数据库是 Microsoft SQL 服务器,托管在 Azure 上。 当我使用离线同步时,数据插入数据库没有问题。但是当我直接调用网络api并在JSON中发送一个对象时,服务器在执行InserAsync时抛出一个未知异常(我将调试器连接到MobileAppService 运行上Azure 找出导致问题的命令):

Exception thrown: 'System.Web.Http.HttpResponseException' in mscorlib.dll

api端点代码简单如下:

public async Task<IHttpActionResult> PostUser([FromBody] User item)
    {            
        User current = await InsertAsync(item);            
        return CreatedAtRoute("Tables", new { id = current.Id , CreatedAt = System.DateTime.Now }, current);
    }

这就是我在 Xamarin 客户端中调用 api 的方式:

var JsonContent = JsonConvert.SerializeObject(user);
var httpContent = new StringContent(JsonContent, System.Text.Encoding.UTF8, "application/json");                    
var response = await httpClient.PostAsync("tables/User/PostUser", httpContent);

令人震惊的是,如果我使用邮递员调用同一个 api 入口点,一切正常。我很困惑,想不出任何其他问题的根源。

我捕获了网络抛出的异常 api 并检查了值。这是手表 window 在远程调试模式下的屏幕截图:

错误可能与 AzureVersion 的值有关,但我不知道如何修复它,因为请求消息的版本设置为 1.1(与调用 api通过邮递员)。

根据你的描述,我检查了Microsoft.Azure.Mobile.Server.dll中的InsertAsync方法,我发现这个错误可能是由几个异常引起的(例如DbEntityValidationException, DbUpdateConcurrencyException, DbUpdateException等。 ) 将数据保存到数据库时。为了定位这个问题,您需要捕获详细的错误消息,您可以按照以下方法:

  • 使用Fiddler从响应中捕获详细错误如下:

  • Remote debug 您的网络应用程序,您可以用 try-catch 包装 InsertAsync 以捕获详细错误,如下所示:

综上所述,您可以尝试定位具体错误并解决。或者您可以提供有关此问题的更详细的错误信息,以便我们找到它。

问题源于使用 AppServiceHelpers.Models.EntityData,它作为 NuGet 包安装。我的实体都继承自 EntityData,它为实体添加了一些属性,其中之一是 AzureVersion:

public class EntityData
{        
    ...       
    [Version]
    public string AzureVersion { get; set; }
}

AzureVersion 标记有属性 [Version] (Microsoft.WindowsAzure.MobileServices.Version)。但是JsonConvert并没有实现这个属性,而是在序列化对象中给这个属性赋了名字AzureVersion(而不是Version),这个在MobileServiceContext中并没有定义后端。

为了解决这个问题,我定义了自己的 EntityData 助手 class,并将 属性 名称显式分配给 Version:

public class MyEntityData
{        
    [Version]
    [JsonProperty(PropertyName = "Version")]
    public string AzureVersion { get; set; }
}

如果没有此解决方法,上下文仅适用于 OfflineSync;因为,Version属性是由MobileServiceClient.SyncContext实现的,对象存储在本地SQLStore中,属性正确设置为Version,然后推送到后端如下SyncContext.PushAsync()。但是,如果您直接将对象推送到后端,属性 将包含 AzureVersion.

的未识别名称