asp.NET mvc,从视图中获取模型列表值

时间:2017-06-13 14:38:11

标签: c# asp.net asp.net-mvc asp.net-mvc-4 razor

我是mvc的新手,我正在尝试执行类似下图中的操作(我不使用部分视图)。 我在Model上有一个IEnumerable属性 Like in this image, (i have not enough reputation to show image directly)

但在控制器上,如果我将FormCollection作为参数接受post方法,当我处理相同的名称字段时,我会得到一个额外的字符',',这也可能被用户使用...

任何想法......

[修改] 我的观点

@model Models.Question
@{
    ViewBag.Title = "Add";
}

<h2>Add</h2>


@using (Html.BeginForm())
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Question</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.SurveyId)
    <div class="form-group">
        @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.QuestionTypeId, "Question type", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.QuestionTypeId, new SelectList(ViewBag.QuestionTypes, "QuestionTypeId", "Name"), new { @class = "form-control col-md-10" })
            <button type="button" class="btn btn-default addAnswer hide"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
            @Html.ValidationMessageFor(model => model.QuestionTypeId, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group hide">
        @Html.LabelFor(model => model.Answers, "Options", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10" id="allAnswers">
            @Html.ValidationMessageFor(model => model.Answers, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Sort, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Sort, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Sort, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Mandatory, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div class="checkbox">
                @Html.EditorFor(model => model.Mandatory)
                @Html.ValidationMessageFor(model => model.Mandatory, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
@Html.ActionLink("Back to List", "Question", "Survey", new { id = Model.SurveyId }, null)
</div>

@section Scripts {
@Scripts.Render("~/bundles/jqueryval", "~/Scripts/QuestionAdd.js")
}

控制器

[HttpGet]
    public ActionResult Add(long id)
    {
        var question = new Models.Question();
        question.SurveyId = id;
        ViewBag.QuestionTypes = BLL.Questions.GetQuestionTypes();
        return View(question);
    }
    [HttpPost]
    public ActionResult Add(FormCollection coll)
    {
        if (ModelState.IsValid)
        {
            var question = new Models.Question();
            question.Name = coll["Name"];
            byte qid = 0, sort = 0;
            bool mandatory = false;
            byte.TryParse(coll["QuestionTypeId"], out qid);
            byte.TryParse(coll["Sort"], out sort);
            bool.TryParse(coll["Mandatory"], out mandatory);
            question.QuestionTypeId = qid;
            question.Sort = sort;
            question.Mandatory = mandatory;
            foreach (var answer in coll["Answers"])
                question.Answers.Add(new Models.Answer() { Value = answer + "" });
            if (question != null)
            {
                if (BLL.Questions.Insert(question) != null)
                    ViewBag.Message = "Successfully inserted";
                else
                    ViewBag.Message = "Insert could not be done";
                return RedirectToAction("Index", "Question", new { questionId = question.QuestionId });
            }
        }
        return View();
    }

点击(+)时

$('#allAnswers').append(
    '<div class="input-group col-lg-4">' +
    '<input class="form-control" name="Answers"> ' +
    '<div class="input-group-btn">' +
    ' <button type="button" class="btn btn-default removeAnswer"><span class="glyphicon glyphicon glyphicon-trash" aria-hidden="true"></span></button>' +
    '</div> </div>');

1 个答案:

答案 0 :(得分:1)

正如所讨论的......这就是我如何处理这个问题。

我有一个视图模型来保存问题和答案以及我们将添加答案的所选问题。

public class CurrentViewModel
{
    public string QuestionSelected { get; set; }
    public List<SelectListItem> Questions { get; set; }
    public List<string> Answers { get; set; }
}

然后在您的控制器中,我们有一个返回视图的操作,一个获取所选问题答案的操作,一个为所选问题添加新答案的操作,以及一个仅显示最终模型内容的保存方法帐。

public class TestController : Controller
    {
        public ActionResult Test()
        {
            var model = new CurrentViewModel()
            {
                Questions = new List<SelectListItem>()
                {
                    new SelectListItem()
                    {
                        Text = "Question 1",
                        Value = "Question 1"
                    },

                    new SelectListItem()
                    {
                        Text = "Question 2",
                        Value = "Question 2"
                    }
                },
                Answers = new List<string>()
            };

            return View("Test", model);
        }

        public PartialViewResult GetAnswers(CurrentViewModel model)
        {
            model.Answers = new List<string>();
            //model.Answers = Get Answers from some service based on QuestionSelected?!
            model.Answers.Add("Answer 1");
            model.Answers.Add("Answer 2"); //Add manuall for example
            return PartialView("_Answers", model);
        }

        public PartialViewResult AddAnswer(CurrentViewModel model)
        {
            model.Answers.Add("Add answer here...");
            return PartialView("_Answers", model);
        }

        public ActionResult SaveQuestionsAndAnswers(CurrentViewModel model)
        {
            if (model.Questions.Count == 0)
            {

            }

            return View("Test", model);
        }

    }

然后我们有一个显示问题下拉列表的主视图和一个可以向我们展示答案的部分视图。

主视图

@model TestMVC.Models.CurrentViewModel

    @{
        ViewBag.Title = "Test";
    }

    <link href="~/Content/StyleSheets/jquery-ui.css" rel="stylesheet" />
    <script src="~/Content/Scripts/jquery-2.2.3.js"></script>
    <script src="~/Content/Scripts/jquery-ui-1.11.4.js"></script>

    <div id="divBodyContent">
        <div>
            <h3>Q & A</h3>
        </div>

        @using (Html.BeginForm("SaveQuestionsAndAnswers", "Test", FormMethod.Post, new { id = "frmQandA" }))
        {
            @Html.Label("lblQ", "Questions", new { @class = "form-control inline" })
            @Html.DropDownListFor(model => model.QuestionSelected, Model.Questions, "Select--", new { @class = "form-control inline", id="ddQuestions" })

            <div id="divAnswers">
                @Html.Partial("_Answers")
            </div>

        <div style="margin-top: 1%;">
            <button id="btnSave" type="submit" class="btn btn-primary" style="margin-left: 4px; margin-bottom: 10px; width: 7%">save</button>
        </div>

        }
    </div>

    <script>
        $("#ddQuestions").on("change", function() {
            var myData = $('#frmQandA').serialize();

            $.ajax({
                type: "POST",
                url: "@Url.Action("GetAnswers", "Test")",
                data: myData,
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
                success: function(data) {
                    $("#divAnswers").html(data);
                }
            })});

    </script>

部分视图

@model TestMVC.Models.CurrentViewModel

<link href="~/Content/StyleSheets/jquery-ui.css" rel="stylesheet" />
<script src="~/Content/Scripts/jquery-2.2.3.js"></script>
<script src="~/Content/Scripts/jquery-ui-1.11.4.js"></script>

<div>
    @for (var counter = 0; counter <= (Model.Answers.Count - 1); counter++)
    {
        @Html.TextBoxFor(model => model.Answers[counter], new {@class = "form-control inline"})
    }

    <div style="margin-top: 1%;">
        <button id="btnAddAnswer" type="button" class="btn btn-primary" style="margin-left: 4px; margin-bottom: 10px; width: 7%">Add</button>
    </div>


</div>

<script>

    $("#btnAddAnswer").on("click", function() {
        var myData = $('#frmQandA').serialize();

        $.ajax({
            type: "POST",
            url: "@Url.Action("AddAnswer", "Test")",
            data: myData,
        contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
        success: function (data) {
            $("#divAnswers").html(data);
        }
    })});

</script>

我已经在本地对此进行了测试,但它确实有效。简而言之,当我们需要在模型中添加新答案时,我们将其添加到服务器端,以便我们可以在浏览器中绑定到模型。我们通过Ajax调用对问题的更改事件进行下拉。部分视图通过计数器遍历每个答案,该计数器为每个答案生成唯一的ID和文本框。通过ajax也可以添加新的答案。然后可以将这些全部发回。

希望有所帮助。