ASP. NET - MVC Отправка и получение модели с контроллера для просмотра и обратно на контроллер - PullRequest
2 голосов
/ 25 января 2020

Я хочу отправить данные, извлеченные из базы данных, в представление, а затем получить данные обратно из представления, чтобы вставить их в базу данных. Моя проблема заключается в работе с 2 экземплярами одной и той же модели.

В основном я хочу показать пользователю 10 случайных вопросов, на которые он может ответить с помощью выбора, а затем я хочу отправить обратно на сервер идентификатор вопроса и выбранный им ответ.

Контроллер:

    public ActionResult Index()
    {
        var questions = db.Questions.Where(p => p.subject == "Subject").ToList();

        var sessionQuestions = questions.OrderBy(item => rand.Next()).Take(10);

        myModel model = new myModel
        {
            Questions = questions,
            randomSample = sessionQuestions,
            submitedAnswers = new Dictionary<int, string>();

        };
        return View(model);
    }
    [HttpPost]
    public ActionResult Index(myModel m)
    {
        ViewBag["Sample"] = m.submitedAnswers;
        return RedirectToAction("Debug");
    }

Просмотр:

@model OnlineQuiz.Models.myModel
@using (Html.BeginForm()) {

    var i = 1;
    foreach (var item in Model.randomSample)
    {
        var possibleAnswers = @item.possibleAnswers.Split(',');

        <div class="question" style="display: block" id=@item.Id runat="server">
            <h4>@i. @item.question</h4>
            <ul runat="server">
                @foreach (var answer in possibleAnswers)
                {
                    <li class="btn btn-primary" style="display: block; margin-bottom:5px" runat="server">@answer</li>
                }
            </ul>
        </div>
        i++;
    }
    <input type="button" id="submit" value="Submit" />
 }

Ответы [ 2 ]

0 голосов
/ 26 января 2020

Что нам нужно сделать, это отправить модель представления, которая содержит структуру для наших вопросов и возможных ответов на представление. Пользователь предоставляет ответы и отправляет ответ обратно на сервер.

В моем проекте я использовал JavaScript для обработки логики c на странице и Ajax для отправки ответа обратно. на сервер.

Я создал свой пример с использованием. net core 3.1 и Microsoft Visual Studio Professional 2019 версии 16.4.2

В JavaScript - каждый ответ отображается в объект:

    var answerObj = {
        id,
        value
    };

answerObj содержит идентификатор вопроса и значение ответа.

Модель представления будет иметь следующую структуру:

public class QuestionStructure
{
    public int Id { get; set; }
    public string Question { get; set; }
    public string PossibleAnswear { get; set; }
}

public class ViewModel
{
    public List<QuestionStructure> Questions { get; set; }

    public ViewModel()
    {
        QuestionStructure q1 = new QuestionStructure
        {
            Id = 1,
            Question = "How many days in a leap year?",
            PossibleAnswear = "2356,366,212,365"
        };
        QuestionStructure q2 = new QuestionStructure
        {
            Id = 2,
            Question = "What is the next number in the series 2, 3, 5, 7, 11...?",
            PossibleAnswear = "15,88,99,13"

        };
        QuestionStructure q3 = new QuestionStructure
        {
            Id = 3,
            Question = "How many wheel has a bike got?",
            PossibleAnswear = "5,3,4,2"
        };

        QuestionStructure q4 = new QuestionStructure
        {
            Id = 4,
            Question = "How many fingers have you got?",
            PossibleAnswear = "5,8,20,10"
        };

        List<QuestionStructure> items = new List<QuestionStructure>();
        items.Add(q1);
        items.Add(q2);
        items.Add(q3);
        items.Add(q4);

        this.Questions = items;
    }
}

Наш контроллер будет выглядеть следующим образом и мы отправляем данные в представление из метода Index:

    private ViewModel viewModel = new ViewModel();

    public IActionResult Index()
    {
        return this.View(viewModel);
    }

    [Route("/homeController/returnedAnswers")]
    public List<ReturnedAnswers> Answers(string json)
    {
        List<ReturnedAnswers> returnedAnswers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ReturnedAnswers>>(json);
        // here you can do all the logic to manipulate your result...
        // We just sent back to the ajax call the json data and we can check it in the console log
        return returnedAnswers;
    }

Страница cs html получит модель типа ViewModel, обратите внимание, что я вставил jQuery как CDN в HTML head:

@model ViewModel;

@{
    ViewData["Title"] = "Home Page";
}

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>

@using (Html.BeginForm())
{
    foreach (var item in Model.Questions)
    {
        var question = @item.Question;
        var possibleAnswers = @item.PossibleAnswear.Split(',');

        <div class="question" style="display: block">
            <div class="row">
                <div class="col-5">
                    <label style="margin-right: 1rem">@question</label>
                </div>
                <div class="col-6">
                    <select class="mySelect">
                        <option value="">Select a question</option>
                        @foreach (var answear in possibleAnswers)
                        {
                            <option value="@item.Id">@answear</option>
                        }
                    </select>
                </div>
            </div>
        </div>
    }
    <input type="button" id="submit" value="Submit" />
}

Самая важная вещь, которую следует здесь отметить, - это для каждого l oop, где мы устанавливаем параметры раскрывающегося списка. Каждая опция будет иметь значение идентификатора вопроса, а текст будет возможным ответом.

Этот дизайн позволит нам позже создать наш объект сопоставления в JavaScript.

Я поместил JavaScript в другой файл - но он может быть встроен непосредственно в страницу.

$(document).ready(function () {

    var answers = [];

    //on change event for all our dropdown
    $(".mySelect").change(function () {

        var id = $(this).children(':selected').attr('value');
        var value = $(this).children(':selected').text();

        var answerObj = {
            id,
            value
        };

        // check if we are changing an already given answer.
        var alreadyIn = answers.find(item => item.id === id);

        //if so remove it from mapped array
        if (alreadyIn) {
            answers = answers.filter(item => item.id !== alreadyIn.id);
        }

        //map selected answer to our array of objects
        answerObj.id = id;
        answerObj.value = value;
        answers.push(answerObj);
    });

    // When the submit button is clicked send the request back to the server.
    // JSON.stringify(answers) will serialise our array of answers - into a Json format.
    $('#submit').on('click', function () {
        $.post({
            url: '/homeController/returnedAnswers',
            dataType: 'json',
            data: { "json": JSON.stringify(answers) },
            success: function (data) {
                console.log(data);
            }
        });
    });
});

То, что делает js, довольно просто.

Каждый раз, когда пользователь выбирает значение из выпадающего списка мы отображаем значение и текст в наш объект:

var answerObj = {
    id,
    value
};

Затем мы сохраняем его в массив.

    answerObj.id = id;
    answerObj.value = value;
    answers.push(answerObj);

Это было бы отображением ответов на идентификаторы вопросов и данных ответов.

Теперь у нас есть структура данных - все, что нам нужно сделать, это отправить ее обратно на сервер.

$('#submit').on('click', function () {
    $.post({
        url: '/homeController/returnedAnswers',
        dataType: 'json',
        data: { "json": JSON.stringify(answers) },
        success: function (data) {
            console.log(data);
        }
    });
});

Я прикрепил событие к кнопке отправки, которая вызовет Ajax пост-вызов моего маршрута (url).

В нашем контроллере я определил свою маршрутизацию следующим методом :

[Route("/homeController/returnedAnswers")]
public List<ReturnedAnswers> Answers(string json)
{
    List<ReturnedAnswers> returnedAnswers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ReturnedAnswers>>(json);
    // here you can do all the logic to manipulate your result...
    // We just sent back to the ajax call the json data and we can check it in the console log
    return returnedAnswers;
}

Метод получит строковый параметр, который будет иметь ту же структуру, что и следующий класс:

public class ReturnedAnswers
{
    public string id { get; set; }
    public string value { get; set; }
}

В результате будет массив объектов - DeserializeObject потребуется использовать List<ReturnedAnswers>

Для целей примера я буду отправлять данные обратно клиенту и отображать их в console.log

Здесь вы можете увидеть результат: enter image description here

Массив, который вы видите в консоли (справа), является ответом от сервера после нажатия кнопки отправки.

0 голосов
/ 25 января 2020

Если можно получить отправленный ответ с идентификатором вопроса в массиве и затем сопоставить его с любой моделью, я бы предложил внести некоторые изменения в контроллер и представления, например:

Представление:

@model OnlineQuiz.Models.myModel
@using (Html.BeginForm())
{
    var i = 1;
    foreach (var item in Model.randomSample)
    {
        var possibleAnswers = @item.possibleAnswers.Split(',');

        <div class="question" style="display: block" id="@item.Id">
            <h4>@i. @item.question</h4>
            <ul">
                @foreach (var answer in possibleAnswers)
                {
                    <li class="" style="display: block; margin-bottom:5px" >
                    <input type="checkbox" id="@item.Id _@answer" name="QuestionAnswer" value="@item.Id _@answer" /> @answer
                    </li>
                }
            </ul>
        </div>
        i++;
    }
    <input type="submit" id="submit" value="Submit" />
}

и в контроллере

[HttpPost]
public ActionResult Index(string[] QuestionAnswer)
{
    // each QuestionAnswer contains only checked value in questionid_answer format
    // like :
    // 1_ansone
    // 1_ansone
    // 2_anstwo
    // 3_ansthree
    foreach(var item in QuestionAnswer){
        int id = Convert.ToInt32(item.Split('_')[0].Trim());
        string answer = item.Split('_')[1].Trim();
        // do save to database or map to model logic here
    }
    return RedirectToAction("Debug");
}

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

...