【问题标题】:Posting an arbitrary amount of text areas发布任意数量的文本区域
【发布时间】:2012-04-28 23:05:35
【问题描述】:

我正在用 C# 编写 ASP.NET MVC3。

我的数据库中有一个包含问题的表。管理员可以添加新问题、编辑问题等。

我有另一个存储问题和答案的表(所以是响应)。

例子:

问题表:

QuestionId........问题

.......1........你好吗?

.......2.......为什么天空是蓝色的?

在我看来,我说“对于每个问题,打印问题并提供一个文本区域来回答问题”

然后我想说“当他们提交时,将每个问答对保存到问答表中”

答案表:

AnswerId........问题........答案

......1.........你好吗?......我很好

......2....为什么天空是蓝色的?......因为

问题是存在任意/可变数量的问题,因此存在任意数量的文本区域。如何将该信息传递给 Post 操作?

编辑

这是我在 Xander 推荐后的看法

@using (Html.BeginForm("QuestionsAndAnswers", "Product"))
{
    int i = 0;
    foreach (var m in Model.Questions)
    {
    i++;
    <div>@m.Body</div>
    @Html.TextArea(string.Format("textareas[{0}]", i))
    <br />
    }
    <input type="submit" value="Save"/>
    @Html.ActionLink("Cancel", "Index", "Home");
}

【问题讨论】:

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


    【解决方案1】:

    使用您的视图....

    @using (Html.BeginForm("QuestionsAndAnswers", "Product"))
    {
    
        foreach (var m in Model.Questions)
        {
        <div class="formfields">
        <input type="hidden" name="QuestionId" id="QuestionId" value="@m.QuestionId" />
        <div>@m.Body</div>
        <textarea name="Answer" id="Answer"></textarea>
        </div>
        }
        <input type="submit" value="Save"/>
        @Html.ActionLink("Cancel", "Index", "Home");
    }
    

    这是用于那个的 Jquery....

    <script type="text/javascript">
        $.fn.serializeObject = function () {
            var o = {};
            var a = this.serializeArray();
            $.each(a, function () {
                if (o[this.name]) {
                    if (!o[this.name].push) {
                        o[this.name] = [o[this.name]];
                    }
                    o[this.name].push(this.value || '');
                } else {
                    o[this.name] = this.value || '';
                }
            });
            return o;
        };
        $(document).ready(function () {
            $("#Submit").click(function () {
                var QuestionAnswerArray = [];
                var QuestionAnswerLength = $(".formfield").length;
                $(".formfield").each(function (i) {
                    var test = $(this).find("textarea, input").serializeObject()
                    QuestionAnswerArray.push(test);
                    if ((i + 1) == QuestionAnswerLength) {
                        $.ajax({
                            type: 'POST',
                            url: '/../Product/QuestionsAndAnswers',
                            data: JSON.stringify(QuestionAnswerArray),
                            contentType: 'application/json; charset=utf-8',
                            dataType: 'json',
                            success: function (return_flag) {                            
                                if (return_flag == true) {
                                    alert("Question and Answers Saved Succesfully!");                                
                                } else {
                                    alert("Error Occured");
                                }
                            }
                        });
                    }
                });
            });
        });
    </script>
    

    然后你在 Controller 中操作....

    [HttpPost]
    public ActionResult QuestionsAndAnswers(Answers[] answers)
    {
                    foreach (var item in answers)
                    {
                        // do whatever you want here
                    }
                    return View();
    }
    

    【讨论】:

    • @Johannes,你可以试试上面的解决方案,我在 asp.net mvc3.. 的 masterdetails 中使用过这个解决方案。
    • 我非常感谢您的帮助和尝试。但是,如果我不需要的话,我不想干预 JQuery。但是当时+1。谢谢。
    【解决方案2】:

    型号:

    public class Question
    {
        public int Id { get; set; }
        public string QuestionText { get; set; }
    }
    
    public class Answer
    {
        public int Id { get; set; }
        public string QuestionText { get; set; }
        public string AnswerText { get; set; }
    }
    

    视图模型:

    public class AnswersViewModel
    {
        public IList<Answer> Answers { get; set; }
    }
    

    控制器:

    public class AnswersController : Controller
    {
        QuestionRepository _questionRepository = new QuestionRepository();
    
        public ActionResult Index()
        {
            AnswersViewModel model = new AnswersViewModel();
            model.Answers = new List<Answer>();
            IEnumerable<Question> questions = _questionRepository.GetRandomQuestions();
            foreach (Question question in questions)
            {
                model.Answers.Add(new Answer() { QuestionText = question.QuestionText });
            }
            return View(model);
        }
    
        [HttpPost]
        public ActionResult Index(AnswersViewModel model)
        {
            //the model will be properly bound here
            return View(model);
        }
    }
    

    视图/答案/Index.cshtml

    @model MvcApplication1.Models.AnswersViewModel
    @{
        ViewBag.Title = "Index";
    }
    @using (Html.BeginForm("Index", "Answers", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.EditorFor(x => x.Answers)
        <input name="submit" type="submit" value="Submit" />
    }
    

    视图/答案/EditorTemplates/Answer.cshtml

    @model MvcApplication1.Models.Answer
    @Html.HiddenFor(x => x.Id)
    @Html.HiddenFor(x => x.QuestionText)
    @Html.DisplayFor(x => x.QuestionText)
    <br />
    @Html.TextAreaFor(x => x.AnswerText)
    <br />
    

    编辑:

    我更新了答案以使其更清楚。

    【讨论】:

    • 哇!我非常感谢这一点。但我认为有一点沟通不畅,这可能是我的错。问题表仅包含问题。答案表包含问题和答案。但问题和答案最初是null。填写完答案后,问题将随其一起发送并存储在答案表中。这是为了确保如果在问题表中编辑问题,旧问题将保留在答案表中。因此,如果管理员更改“你好吗?” “你喜欢香蕉吗?”它也不会显示为“你喜欢香蕉吗?我很好”。
    • 希望这更有意义。因为现在这种设置方式只允许每个问题有 1 个答案。我需要一个问题的无限答案
    • 没有误传。我只展示了如何发布Answers,但我将课程称为QuestionWithAnswer。你可以有一个Questions 表,你可以用它来加载问题。
    • 谢谢大卫。这很好用。我会接受你的回答并奖励你。你应得的!再次感谢你。
    【解决方案3】:

    我们可以编写控制器来接收来自模型或视图模型的数组,但数组不是 ORM 友好的(如果您打算直接使用域模型来查看视图)。考虑到这一点,我们的控制器视图将在IList 上运行; IList 很灵活,它不受元素数量的限制,不像数组;与数组相比,IList 是 ORM 就绪的。

    我们应该做的唯一调整是在视野中; HTML 或者更确切地说是 javascript,没有列表的概念,它只能使用数组或关联数组。承认这一限制,我们会将这些项目从 List&lt;ClassType&gt; 发送到 javascript 友好的数组。

    最后,当我们提交时,我们友好的社区 ASP.NET MVC 将为我们处理这些事情,即它可以根据 HTML/javascript 提交的数组自动填充我们的 List&lt;ClassType&gt; 变量,即不需要让我们迭代Request.Form,不需要手动填充,我们的代码操作的一切都是以模型/视图模型为中心的,因为它们应该是。 ASP.NET MVC 程序员的生活很美好不是吗? ;-)

    完整代码如下:


    型号:

    namespace SoQna.Models
    {
        public class Question
        {
            public int QuestionId { get; set; }
            public string QuestionText { get; set; }
        }
    
        public class Answer
        {
            public int AnswerId { get; set; }
            public Question Question { get; set; }
            public string AnswerText { get; set; }
        }
    }
    

    视图模型:

    using System.Collections.Generic;
    
    namespace SoQna.ViewModels
    {
        public class QnaViewModel
        {
            public IList<AnswerToQuestion> Answers { get; set; }
        }
    
        public class AnswerToQuestion
        {
            public int ToQuestionId { get; set; }
            public string QuestionText { get; set; }
            public string AnswerText { get; set; }
        }
    }
    

    控制器:

    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    
    namespace SoQna.Controllers
    {
      public class HomeController : Controller
      {
        IList<SoQna.Models.Question> _qnaRepo = new List<SoQna.Models.Question>
        {
          new SoQna.Models.Question { QuestionId = 1, 
            QuestionText = 
              "Why is there a proliferation of different kind of ORMs?" 
          },
          new SoQna.Models.Question { 
              QuestionId = 2, QuestionText = "How are you?" 
          },
          new SoQna.Models.Question { 
              QuestionId = 3, QuestionText = "Why the sky is blue?" 
          },          
          new SoQna.Models.Question { 
              QuestionId = 4, QuestionText = "Why is MVC the bees knees?" 
          },          
        };
    
    
        public ActionResult Index()
        {
          var qna = new SoQna.ViewModels.QnaViewModel { 
              Answers = new List<SoQna.ViewModels.AnswerToQuestion>() 
          };
    
          foreach (var question in _qnaRepo)
          {
            if (question.QuestionId == 1) continue; // subjective :-)
    
            qna.Answers.Add(
              new SoQna.ViewModels.AnswerToQuestion { 
                  ToQuestionId = question.QuestionId, 
                  QuestionText = question.QuestionText, 
                  AnswerText = "Put your answer here" 
              }
            );         
          }
    
          return View(qna);
        }
    
        [HttpPost]
        public ViewResult SubmitAnswers(SoQna.ViewModels.QnaViewModel a)
        {
          foreach (var answer in a.Answers)
          {
            answer.QuestionText = _qnaRepo.Single(x => 
               x.QuestionId == answer.ToQuestionId).QuestionText;
          }
          return View(a);
        }
    
      }//HomeController
    }//namespace
    

    主页/索引视图

    @model SoQna.ViewModels.QnaViewModel
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Hahah</h2>
    
    @using (Html.BeginForm("SubmitAnswers", "Home"))
    {
    
    
        int i = 0;
        foreach (var answer in Model.Answers)
        {
            @: Question #@(answer.ToQuestionId) <br />
    
            @Html.Hidden("Answers[" + i + "].ToQuestionId", answer.ToQuestionId)
    
            @Html.Label("Answers[" + i + "].QuestionText", answer.QuestionText)
    
            @* 
               to save bandwidth we didn't include QuestionText on submit, 
               this is done by assigning it on Label, and no need to persist 
               QuestionText on Hidden 
            *@
    
            <br />
    
            @Html.TextArea("Answers[" + i + "].AnswerText", answer.AnswerText)
    
            <hr />
    
            ++i;
    
        }
    
        <input type="submit" value="Done" />
    }
    

    查看主页/提交答案

    @model SoQna.ViewModels.QnaViewModel
    
    @{
        ViewBag.Title = "SubmitAnswers";
    }
    
    <h2>SubmitAnswers</h2>
    
    
    @foreach (var item in Model.Answers)
    {
        @: Answer to question: @item.QuestionText
        <br />    
        @item.AnswerText
    
        <hr />
    }
    

    【讨论】:

      【解决方案4】:

      我建议建立隐藏字段,如下所示:

      <input type="hidden" name="questionsAndAnswers" 
      value="[{'id':questionId, 'question':questionName, 'answer':answerName}, 
              {'id':questionId, 'question':questionName, 'answer':answerName}...] />
      

      然后你序列化发布的隐藏值

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多