В моем проекте у меня есть одно представление, которое динамически заполняется, создавая одну или несколько форм на одном экране/странице. Мне удалось динамически предоставить каждой форме уникальный идентификатор, однако при наличии нескольких форм на одной странице массив всех форм возвращается, когда отправляется только один, и я не знаю, как идентифицировать фактический экземпляр, который отправляется с массив.Несколько динамических форм в одном представлении MVC
вот мой взгляд;
@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);
}
}
}
Есть еще вопросы типа типа, но я оставил их для ясности.
При наличии более одного вопроса и ответа на экран действие post возвращает массив всех форм на странице. Из моих первоначальных исследований я не вижу, как определить, какая конкретная форма подана, поэтому я не знаю, как вывести правильный ответ.
Есть ли способ?
Итак, я бы поместил форму в частичный вид и дал каждому частичному виду форму уникального имени? Я не уверен, что получаю, как это сделать. Можете ли вы указать мне пример, пожалуйста? – Alex