为了账号安全,请及时绑定邮箱和手机立即绑定

序列化 ListView 数据以发送 JSON POST

序列化 ListView 数据以发送 JSON POST

C#
沧海一幻觉 2022-01-16 15:35:53
我正在关注这个问题ListView Get Multiple Entry Values to validate and send我现在需要序列化数据以将其发送到服务器,我已经做到了这一点:public class SurveyList{    public List<QuestionList> Questions { get; set; }}public class QuestionList{    public string QuestionLabel { get; set; }    public string QuestionCode { get; set; }}public partial class SurveyPage : ContentPage{    private List<QuestionList> survey;    public SurveyPage()    {        InitializeComponent();        survey = new List<QuestionList>        {            new QuestionList { QuestionLabel = "Question 1?", QuestionCode = "01" },            new QuestionList { QuestionLabel = "Question 2?", QuestionCode = "02" }        };        surveyList.ItemsSource = survey;    }    void Button_Clicked(object sender, System.EventArgs e)    {        HttpClient client = new HttpClient();        client.BaseAddress = new Uri("http://myip");        foreach (var getValues in survey)        {            Dictionary<string, string> listViewData = new Dictionary<string, string>()            {                { "Question", getValues.QuestionLabel },                { "Answer", getValues.QuestionCode }            };            var listViewDataContent = new FormUrlEncodedContent(listViewData);            var response = client.PostAsync("/api/GetData", listViewDataContent);        }    }}请帮助我正确获取所有数据以通过 POST 发送。不知道如何收集所有数据,因为我得到的数据是动态的。注意:那里显示的数据是静态的,但应该是从同一个 API 获取数据
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

您不必手动编写 Json,还有其他方法可以做到这一点。


首先修改您的QuestionList对象以调用另一个字段,Answer或者您更喜欢调用它。


public class QuestionList

{

    public string QuestionLabel { get; set; }

    public string QuestionCode { get; set; }

    public string Answer { get; set; }

}

这个新属性将保存答案的值。


第二:改变你List<QuestionList>的 ObservableCollection


这里:


private ObservableCollection<QuestionList> survey;

和这里


survey = new ObservableCollection<QuestionList>

{

    new QuestionList { QuestionLabel = "Question 1?", QuestionCode = "01" },

    new QuestionList { QuestionLabel = "Question 2?", QuestionCode = "02" }

};

稍微改变一下你的 XAML。将 绑定Answer到Picker SelectedItem. 这就是“魔术”发生的地方。


<Picker x:Name="QuestionPicker" 

        SelectedItem="{Binding Answer, Mode=TwoWay}">

    <Picker.Items>

        <x:String>Yes</x:String>

        <x:String>No</x:String>

    </Picker.Items>

</Picker>

每次用户从中选择一个值时,Picker它都会自动更新Answer您设置为的 List 的属性ItemsSource。更多关于绑定在这里


现在您只需更改 Button Clicked 事件,使用这行代码您将拥有一个做得很好的 Json。(首先你需要安装Newtonsoft Nugget)


这里有一个教程,展示了如何安装一个 nugget 包(巧合的是,他们使用相同的库作为示例,我们很幸运!)。


var json = JsonConvert.SerializeObject(survey);

上面将创建一个具有以下格式的 json:


[

    {

        "QuestionLabel":"Question 1",

        "QuestionCode" : "01",

        "Answer":"No"

    },

    {

        "QuestionLabel":"Question 2",

        "QuestionCode" : "02",

        "Answer":"Yes"

    },

    {

        "QuestionLabel":"Question 3",

        "QuestionCode" : "03",

        "Answer":"Yes"

    },

    {

        "QuestionLabel":"Question 4",

        "QuestionCode" : "04",

        "Answer":"Yes"

    },

    {

        "QuestionLabel":"Question 5",

        "QuestionCode" : "05",

        "Answer":"No"

    }

]

如您所见,这表示一个 QuestionList 数组,并且您的服务器端点应该期望它作为请求正文。为了清楚起见,我Answer用随机值填充。


整个 Click 事件代码看起来像


void Button_Clicked(object sender, System.EventArgs e)

{

    using(var client = new HttpClient())

    {

        client.BaseAddress = new Uri("http://myip");


        var json = JsonConvert.SerializeObject(survey);


        var listViewDataContent = new FormUrlEncodedContent(json);

        var response = client.PostAsync("/api/GetData", listViewDataContent);

    }

}

注意:请注意,我对初始化 HttpClient 的方式进行了一些更改。是的,我知道该文档存在,但是您每次单击按钮时都会创建一个新实例,因为这不是问题的一部分,以免说我们没有看到它。


注意 2:将值与服务器在 json 中的期望值匹配。这里重要的是向您展示使用Xamarin.Forms绑定您可以从中获取值,ListView并且使用Newtownsoft.Json您可以轻松地将数据从C# Object 转换为Json。更多关于这个库的信息在这里。



查看完整回答
反对 回复 2022-01-16
?
浮云间

TA贡献1829条经验 获得超4个赞

好的,所以我解决了,感谢@apineda 和@Andrew,他们将我引导到正确的方向。也许解决方案没有它可以的那么干净,但它确实有效。


第 1 步 - 模型


我有两个班级


调查列表

问题清单


public class SurveyList

{

    [JsonProperty("title")]

    public string SurveyTtitle { get; set; }

    [JsonProperty("questions")]

    public List<QuestionList> Questions { get; set; }

}


public class QuestionList

{

    [JsonProperty("question")]

    public string QuestionText { get; set; }

    [JsonProperty("questionId")]

    public string QuestionCode { get; set; }

}

第 2 步 - 我的 Xaml


我的 ListView 标题的标题


<ListView.Header>

    <StackLayout Padding="0, 30" VerticalOptions="CenterAndExpand">

        <Label x:Name="surveyTitle" Text="" FontSize="18" FontAttributes="Bold" HorizontalOptions="Center"/>

    </StackLayout>

</ListView.Header>

ListView 项目模板


<ListView.ItemTemplate>

    <DataTemplate>

        <ViewCell>

            <StackLayout Padding="5, 5, 5, 15" VerticalOptions="Start" HorizontalOptions="FillAndExpand">

                <Label Text="{Binding QuestionText}"/>

                <Picker ItemDisplayBinding="{Binding QuestionCode}" Title="Select Yes or No" FontSize="Small" TextColor="Gray" SelectedIndexChanged="Handle_SelectedIndexChanged">

                    <Picker.Items>

                        <x:String>Yes</x:String>

                        <x:String>No</x:String>

                    </Picker.Items>

                </Picker>

            </StackLayout>

        </ViewCell>

    </DataTemplate>

</ListView.ItemTemplate>

用于发送数据的按钮的 ListView 页脚


<ListView.Footer>

    <StackLayout Padding="0, 30, 0, 30">

        <Button x:Name="surveyButton"

                Text="Send Survey"

                TextColor="White"

                BackgroundColor="Teal"

                Clicked="Handle_Clicked" />

    </StackLayout>

</ListView.Footer>

第 3 步 - 我的 CodeBehind


我添加了参数、IDictionary、baseURI、API 和资源


    private IDictionary<string, string> Answers;

    private string baseUri = "http://myip";

    private string api = "/api";

    private string resource = "/GetData";

    private string username = "username";

    private string password = "password";

在构造函数中,我实例化了 Dictionary 对象


    Answers = new Dictionary<string, string>();

添加了一个覆盖 OnAppearing() ,因此每次调用该页面时,它都会调用 API 并检查它们是否有可用的调查(注意:@apineda,抱歉,没有添加您的代码,这更干净,但我已经在编写它了)


    HttpClient client = new HttpClient();

        client.BaseAddress = new Uri(baseUri);

        client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password)));

        client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("Application/json"));


        var response = client.GetAsync(api).Result;


        if (response.IsSuccessStatusCode)

        {

            var getJson = client.GetStringAsync(api + resource).Result;

            var jsonString = JsonConvert.DeserializeObject<SurveyList>(getJson);


            surveyTitle.Text = jsonString.SurveyTtitle;

            Survey = new List<QuestionList>();


                foreach (var surveys in jsonString.Questions)

                {

                    Survey.Add(new QuestionList { QuestionText = surveys.QuestionText, QuestionCode = surveys.QuestionCode });

                }


                surveyList.ItemsSource = Survey;

                surveyList.EndRefresh();


                stackButton.IsVisible = true;


        }

        else

        {

            surveyTitle.Text = "No Surveys Available";

        }

选择器选择索引更改以在每次更改时将值添加到答案字典


    void Handle_SelectedIndexChanged(object sender, System.EventArgs e)

    {


        var picker = sender as Picker;


        var item = picker.BindingContext;


        var question = item as QuestionList;


        Answers.Add(question.QuestionCode, picker.SelectedItem.ToString());

    }

发送所有数据的按钮方法


    void Handle_Clicked(object sender, System.EventArgs e)

    {


        HttpClient client = new HttpClient();

        client.BaseAddress = new Uri(baseUri);

        client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(username + ":" + password)));


        foreach (KeyValuePair<string, string> item in Answers)

        {

            Dictionary<string, string> collectAnswers = new Dictionary<string, string>()

            {

                 { item.Key, item.Value }

            };

        }

         var collectAnswersContent = new FormUrlEncodedContent(collectAnswers);


         var response = await client.PostAsync(api + "/addSurveyAnswers", collectAnswersContent);


         if (response.IsSuccessStatusCode)

         {

             await DisplayAlert(null, "Thank you for answering the survey", "Close");

             (sender as Button).BackgroundColor = Color.FromHex("#00afb9");


         }

         else

         {

             await DisplayAlert("Error", "Please Try Again, something went wrong", "OK");

             (sender as Button).BackgroundColor = Color.FromHex("#00afb9");

         }

    }

我知道这段代码不是很干净(Xamarin 和 C# 的新手),只是想发布答案以防有人发现它有用。我违反了程序员法,我在很多地方都在重复自己,但到目前为止它仍然有效,现在我可以开始清理代码了


查看完整回答
反对 回复 2022-01-16
  • 2 回答
  • 0 关注
  • 175 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信