【发布时间】:2020-01-02 05:50:36
【问题描述】:
我有一个内置于 Xamarin.Forms 的数据输入应用程序,旨在将数据捕获为特定格式,然后通过 ASP.NET Web 服务将其发布到 SQL Server 中。我正在使用RestSharp 来简化此操作。以下是我目前必须这样做的代码:
private async void Button_Clicked(object sender, EventArgs e)
{
try
{
string userResponse = await DisplayActionSheet("Are you sure?", "Yes", "No");
if (userResponse == "Yes")
{
using (SQLiteConnection conn = new SQLiteConnection(App.DatabaseLocation))
{
List<DataToBeSent> d = conn.Query<DataToBeSent>("select * from DataToBeSent");
var dConvert = JsonConvert.SerializeObject(d, Formatting.Indented);
var client = new RestClient("url here");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
Token token = conn.Query<Token>("select * from Token").FirstOrDefault();
request.AddHeader("Authorization", "Bearer " + token.access_token);
request.AddParameter("application/json", dConvert, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
await DisplayAlert("", response.StatusCode.ToString() + response.Content.ToString(), "OK");
}
await Navigation.PopToRootAsync();
}
}
catch (Exception ex)
{
await DisplayAlert("Error", $"Data failed to be inserted.\n{ex}", "OK");
}
}
Token 类使用成功的 POST 请求来检索 OAuth 令牌,以便应用在启动时使用 GET 数据。
值得注意的是,我要发布数据的表没有主键。很遗憾,但要求它没有主键。 表现在有一个主键(名为UniqueID)。我还注意到List<DataToBeSent> 在序列化时返回转义字符。为什么会出现这些错误?有谁知道怎么解决?
更新 1: 应要求; JSON 传递如下。
"[\n {\n \"column1\": \"data1\",\n \"column2\": \"data2\"\n }\n]"
数据库模型代码如下。
<!--Errors Found During Generation:
warning 6002: The table/view 'databaseName.dbo.DataToBeSent' does not have a primary key defined. The key has been inferred and the definition was created as a read-only table/view.-->
<EntityType Name="DataToBeSent">
<Key>
<PropertyRef Name="column1" />
<PropertyRef Name="column2" />
</Key>
<Property Name="column1" Type="nvarchar" MaxLength="50" Nullable="false" />
<Property Name="column2" Type="nvarchar" MaxLength="50" Nullable="false" />
</EntityType>
<EntitySet Name="DataToBeSent" EntityType="Self.DataToBeSent" store:Type="Tables" store:Schema="dbo">
<DefiningQuery>
SELECT
[DataToBeSent].[column1] AS [column1],
[DataToBeSent].[column2] AS [column2]
</DefiningQuery>
</EntitySet>
更新 2: 我已尝试在 Xamarin 后端更新我的 POST 请求代码。这是我目前拥有的。
List<DataToBeSent> DATA = conn.Query<DataToBeSent>("select * from DataToBeSent");
var data = JsonConvert.SerializeObject(DATA, Formatting.None);
Token token = conn.Query<Token>("select * from Token").FirstOrDefault();
var client = new RestClient("url");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer " + token.access_token);
request.AddJsonBody(data);
IRestResponse response = client.Execute(request);
await DisplayAlert("Response", response.StatusCode + response.Content, "OK");
我不知道为什么会发生序列化错误 - 在 Visual Studio 中将结果作为JSON 对象查看时,转义字符不存在。这将向我表明序列化正在正确发生,但我仍然收到相同的错误消息(BadRequest)。我正在尝试提交对象的List<>,所以我想知道JsonConvert.SerializeObject 是否是正确的使用方法。
更新 3: 我已尝试按照下面@Mat J 的建议发布单个对象。代码与更新 2 相同,只是将 List<> 对象更改为带有 .FirstOrDefault() 的单个对象。见下文。
DataToBeSent DATA = conn.Query<DataToBeSent>("select * from DataToBeSent").FirstOrDefault();
var data = JsonConvert.SerializeObject(DATA, Formatting.None);
以下是来自网络服务的控制器代码。我将其自动生成为Web API 2 Controller, using Entity Framework,并在其上方添加方括号以使用我的 OAuth 安全方法。
[Authorize(Roles = "Admin, User")]
[HttpPost]
[Route("api/v/DataToBeSent")]
[ResponseType(typeof(DataToBeSent))]
public IHttpActionResult PostDataToBeSent(DataToBeSent dataToBeSent)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.DataToBeSent.Add(dataToBeSent);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if (DataToBeSentExists(dataToBeSent.UniqueID))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = dataToBeSent.UniqueID }, dataToBeSent);
}
DataToBeSent 表现在有一个主键,名为 UniqueID,如上所述。
我确实希望能够提交整个 List<> 对象,而不是执行类似 for 循环的操作并为列表中的每个单独对象单独调用 POST。
【问题讨论】:
-
第一个错误消息非常清楚 - 它需要一个对象并且您正在传递一个数组。它甚至提供了如何修复它的建议。但是您还没有向我们展示 1) 模型的代码,2) 正在传递的 json,以及 3) Web 服务的签名,因此无法告诉您可能需要更改什么
-
第二个错误似乎是 EF 问题。谷歌搜索错误消息会返回数百个点击,其中一些来自之前关于 SO 的问题
-
添加1)和2),如何找到webservice的签名? @Jason 是的,我尝试了几种解决方案,例如删除 DefiningQuery 并将 store:Schema 更新为仅 Schema,这两种方法都不适合我。
-
如果您还不清楚,则在 Web 服务中生成错误。您正在发送一个数组,Web 服务具有类似于
public ActionResult ApiEndpoint(DataToBeSent model)的签名,而您像ApiEndpoint(listOfDataToBeSent)一样调用它会导致错误。通过在查询末尾添加FirsOrDefault调用来发送一个对象。 -
请在最近的编辑中查看
FirstOrDefault的测试结果。
标签: c# asp.net xamarin json.net restsharp