为什么我的ASP.NET Web服务无法完成此POST请求?

问题描述 投票:1回答:1

我有一个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数据。

我还与Postman进行了测试,以下样品要求:enter image description hereenter image description here

这会在我的Web服务中导致以下错误:enter image description here

值得注意的是,我要向其发布数据的表没有主键。不幸的是,但是它必须没有一个主键。 表现在具有主键键(名为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>

Update 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是否是使用的正确方法。

Update 3:我已经尝试过发布以下@Mat J建议的单个对象。除了将List<>对象更改为带有.FirstOrDefault()的单个对象外,代码与Update 2相同。见下文。

DataToBeSent DATA = conn.Query<DataToBeSent>("select * from DataToBeSent").FirstOrDefault();
var data = JsonConvert.SerializeObject(DATA, Formatting.None);

响应显示在应用程序中。enter image description here

下面是我的控制器从Web服务获得的代码。我自动将其生成为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调用。

c# asp.net xamarin json.net restsharp
1个回答
0
投票

我建议阅读RestSharp文档。我们试图使它更易于使用,但我不确定您为什么不从中受益。

让我们看一下这段代码:

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);
  • 首先,AddJsonBody接受一个object,该序列会为您序列化。您要发送的string已经包含序列化的对象,因此它将永远无法使用。

  • 通过调用AddJsonObject,您已经将内容类型设置为application/json,无需再次执行。

  • 代替手动设置承载头,您可以只使用为验证目的而构建的JwtAuthenticator,而无需为每个请求操纵头。

  • 建议客户端为单例,不要为每个请求重新创建。

我可以建议使用以下内容:

public void WhateverIsCalledOnce()
{
    var roken = conn.Query<Token>("select * from Token").First();
    _client = new RestClient("url").UseNewtonsoftJson();
    _client.Authenticator = new JwtAuthenticator(token.access_token);
}

public async Task CallRemoteServer()
{
    var data = await _connection.GetDataFromDb("query");
    var request = new RestRequest("/api/v/DataToBeSent")
        .AddJsonBody(data);
    var result = await _client.PostAsync<DataToBeReturned>(request);
}

UseNewtonsoftJson扩展方法在NuGet的RestSharp.Serializers.NewtonsoftJson程序包中。

© www.soinside.com 2019 - 2024. All rights reserved.