Сериализация ListView Data для отправки JSON POST - PullRequest
0 голосов
/ 13 сентября 2018

Я слежу за этим вопросом ListView Получить несколько значений ввода для проверки и отправки Мне нужно теперь сериализовать данные для отправки их на сервер, у меня так далеко:

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

Спасибо

Редактировать: добавление моего кода Xaml

<ListView x:Name="surveyList"
      HasUnevenRows="true"
      SeparatorVisibility="Default" 
      BackgroundColor="White">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Padding="10" BackgroundColor="Purple">
                    <StackLayout Spacing="10" VerticalOptions="Start" HorizontalOptions="FillAndExpand" BackgroundColor="Olive">
                        <Label Text="{Binding QuestionLabel}" TextColor="Navy"/>
                        <Picker x:Name="QuestionPicker">
                            <Picker.Items>
                                <x:String>Yes</x:String>
                                <x:String>No</x:String>
                            </Picker.Items>
                        </Picker>
                    </StackLayout>
                    <StackLayout Spacing="20" VerticalOptions="End" HorizontalOptions="FillAndExpand" BackgroundColor="Maroon">
                    <Button x:Name="surveyButton"
                            Text="Enviar"
                            TextColor="White"
                            BackgroundColor="{StaticResource dpGreen}"
                            Clicked="Handle_Clicked"/>
                    </StackLayout>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.Footer>
        <Button x:Name="surveyButton"
            Text="Send"
            TextColor="White"
            BackgroundColor="Teal"
            Clicked="Handle_Clicked" />
    </ListView.Footer>
</ListView>

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Хорошо, я решаю это благодаря @apineda и @Andrew, которые направили меня в правильном направлении.Возможно, решение не такое чистое, как могло бы быть, но оно работает.

Шаг 1 - Модель

У меня есть два класса

  • SurveyList
  • QuestionList

    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 #), просто хотел опубликовать ответ на тот случай, если кто-то может его найтиполезно.Я нарушаю закон программистов, я повторяюсь во многих местах, но он работает до сих пор, и теперь я могу начать очищать код

Еще раз спасибо всем !!!Счастливое кодирование

0 голосов
/ 14 сентября 2018

Вам не нужно составлять свой 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 списка, который вы задали как ItemsSource. Подробнее о привязках здесь

Теперь вы просто измените событие нажатия кнопки, и с этой строкой кода у вас будет хорошо сделанный Json. (Сначала вам нужно установить Newtonsoft 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 Binding вы можете получить значения из ListView, а также с помощью Newtownsoft.Json вы можете легко конвертировать ваши данные из a C # Объект для Json . Подробнее об этой библиотеке здесь .

Надеюсь, это поможет .-

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...