【问题标题】:Multiple dynamic forms in one view MVC一个视图MVC中的多个动态表单
【发布时间】:2014-01-28 11:01:52
【问题描述】:

在我的项目中,我有一个动态填充的视图,在一个屏幕/页面上创建一个或多个表单。我设法动态地给每个表单一个唯一的 id,但是当一个页面上有多个表单时,当只提交一个时返回所有表单的数组,我不知道如何识别正在提交的实际实例数组。

这是我的观点;

@using Microsoft.AspNet.Identity
@model IEnumerable<Template.Models.GetQuestionViewModel>
@{
   ViewBag.Title = "View question";
   ViewBag.Page = Model.First().PageNumber;
}
@Html.AntiForgeryToken();
@foreach (var q in Model.OrderBy(o => o.QuestionRanking))
{
Html.BeginForm("ViewQuestion", "Question", FormMethod.Post, new { @class = "form-horizontal", id = @q.formNumber, role = "form" });
var qtype = q.QuestionTypeId;
<div>
    <h1>@q.QuestionRanking. @q.Question1</h1>
</div><div class="form-group">
    @switch (qtype)
    {
        case 1:
            // Textbox
            @Html.TextArea("Answer", q.Answer, new { @class = "form-control",  rows="4", cols="10" })
            break;

        case 2:
            //  Dropdown
            <select class="form-control" id="Answer" name="Answer">
                @foreach (var item in q.QuestionOptions.OrderBy(o => o.QuestionOptionRanking))
                {
                    if (q.Answer == item.QuestionOption1)
                    {
                        <option value="@item.QuestionOption1" selected>@item.QuestionOption1</option>
                    }
                    else
                    {
                        <option value="@item.QuestionOption1">@item.QuestionOption1</option>
                    }
                }
            </select>
                break;
...
    }
    </div>
    <input type="hidden" name="QuestionId" value="@q.Id" /
    <div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" name="@q.formNumber" class="btn btn-primary" value="Save answer" />
    </div>
</div>
<br />
<hr />
**Html.EndForm();**
}

这是我的控制器;

using System.Web.Mvc;
using Template.Models;
using Microsoft.AspNet.Identity;
using System.Linq;
using System.Collections.Generic;
using System;

namespace Template.Controllers
{
public class QuestionController : Controller
{
    private WebTemplateEntities db = new WebTemplateEntities();

    // GET: /Questions/ViewQuestion/5
    [HttpGet]
    public ActionResult ViewQuestion(int page = 1)
    {
        // If user is not logged in, push them back to Login
        var userId = User.Identity.GetUserId();
        if (userId == null)
        {
            return RedirectToAction("Login", "Account");
        }
        // Get the list of Questions and Response options from the database
        List<GetQuestionViewModel> quest = new List<GetQuestionViewModel>();

        var i = 1; // for form array

        foreach (var item in db.Questions.Where(q => q.PageNumber == page))
        {
            //Check if user has submitted a response
            var reply = db.Responses.Where(r => r.QuestionId == item.Id && r.UserId == userId).Select(r => r.Answer).ToList();
            //If no input, do not look for answers
            if (reply.Count == 0)
            {
                quest.Add(new GetQuestionViewModel()
                {
                    Id = item.Id,
                    QuestionOptions = db.QuestionOptions
                    .Where(k => k.QuestionId == item.Id)
                    .ToList(),
                    PageNumber = item.PageNumber,
                    Question1 = item.Question1,
                    QuestionRanking = item.QuestionRanking,
                    QuestionTypeId = item.QuestionTypeId,
                    formNumber = "form" + i // for form array
                });
            }
            else //If user has input answers find them
            {
                quest.Add(new GetQuestionViewModel()
                {
                    Id = item.Id,
                    QuestionOptions = db.QuestionOptions
                    .Where(k => k.QuestionId == item.Id)
                    .ToList(),
                    PageNumber = item.PageNumber,
                    Question1 = item.Question1,
                    QuestionRanking = item.QuestionRanking,
                    QuestionTypeId = item.QuestionTypeId,
                    formNumber = "form" + i, // for form array
                    Answer = reply.First()
                });
            }        
            i++; // for form array
        }
        return View(quest);
    }

    // POST: /Questions/ViewQuestion/5
    [HttpPost]
    public ActionResult ViewQuestion([Bind(Include = "QuestionId, Answer, UserId")] ResponseViewModel responseViewModel)
    {
        // Get page and question id
        var page = System.Web.HttpContext.Current.Request["page"];  //NOTE: Problem with binding on multi form pages
        var qId = System.Web.HttpContext.Current.Request["QuestionId"]; //NOTE: Problem with binding on multi form pages
        var newAnswer = System.Web.HttpContext.Current.Request["Answer"]; 
        int a = Convert.ToInt32(qId);   //NOTE: Problem with binding on multi form pages

        //Check if user has previously answerer
        List<Response> reply = new List<Response>();
        reply = (from r in db.Responses
                    where r.QuestionId == a && r.UserId == responseViewModel.UserId
                    select r ).ToList();

        // If this is the first time the user has answered, add the response
        if (reply.Count() == 0)
        {
            Response re = new Models.Response();
            re.Answer = responseViewModel.Answer;
            re.UserId = responseViewModel.UserId;
            re.QuestionId = responseViewModel.QuestionId;
            re.Source = "Web";
            re.Status = "New";
            re.DateStamp = System.DateTime.Now;
            db.Responses.Add(re);
            db.SaveChanges();
        }
        else // If the user has already answered move the original responses to AuditTrail
        {
            var ans = reply.Select(r => r.Id).First();
            var dos = reply.Select(r => r.Answer).First();
            AuditTrail au = new Models.AuditTrail();
            au.ResponseId = ans;
            au.OriginalData = dos;
            au.DateChanged = System.DateTime.Now;
            db.AuditTrails.Add(au);
            db.SaveChanges();

            // Update user's response
            var stat = "Update, 1"; // NOTE: Work in progress; create array of updates to track number of updates
            var updateAnswer = db.Responses.Single(q => q.Id == ans);
            updateAnswer.Answer = newAnswer;
            updateAnswer.Status = stat;
            db.SaveChanges();
        }
            return RedirectToAction("ViewQuestion/" + page);
    }
  }
}

还有更多问题类型的案例,但为了清楚起见,我将它们省略了。

如果每个屏幕有多个问题和响应,则发布操作会返回页面上所有表单的数组。从我最初的调查来看,我无法确定如何确定提交了哪个特定表单,因此我不知道如何获得正确的回复。

有办法吗?

【问题讨论】:

    标签: c# asp.net-mvc model-view-controller view


    【解决方案1】:

    MVC 中有一个叫PartialView的概念。您可以使用它来在单个页面中呈现多个表单。

    【讨论】:

    • 所以我会把表单放在局部视图中并给每个局部视图表单一个唯一的名称?我不确定我该怎么做。请给我举个例子好吗?
    【解决方案2】:

    我觉得自己多么愚蠢!我没有关闭表单!

    对于那些在同样问题上苦苦挣扎的人,只需使用 Html.EndForm(); 关闭即可

    我将它放在视图的最后一行之后,现在它只返回提交表单中的值。

    我的老板发现了......不是个好日子!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-04
      • 2020-06-24
      • 2016-02-19
      相关资源
      最近更新 更多