2015-01-05 110 views
1

我有考試的視圖模型。每個考試都有任意數量的問題。這可能是1個問題,也可能是50個問題。提交後,我需要循環回答問題並檢查答案。我有一個解決方案,但我覺得這不是一個最佳做法。ASP.NET MVC處理控制器中動態參數數量的最佳方法

int questionNumber = 1; 

     while (Request.Form["Question" + questionNumber.ToString()] != null) 
     { 
      int questionID = Convert.ToInt32(Request.Form["Question" + questionNumber.ToString()]); 
      int answerID = Convert.ToInt32(Request.Form["Answer" + questionNumber.ToString()]); 

      //TODO: Check if answer is correct 
     } 

的不確定另一種方式來做到這一點像

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult GradeTest(int? testID, string[] questionIDs, string[] answerIDs) 

我在做什麼感覺有點哈克。請幫助或讓我知道我在正確的軌道上。謝謝!

+4

不要這樣做。以正確的方式做,使用ViewModel。您正在採用ASP.NET MVC的一些核心方面並將它們拋出窗口。它可以幫助你瀏覽一些教程 – Jonesopolis

+0

Yeah Jonesy這樣做完全傷害了我。 – kcabrams

回答

3

我真的不明白整個上下文,但是如果這是從視圖的形式提交,那麼表單可能使用@ Html.TextBoxFor或類似的東西來構建。只需採用與發佈後操作相同的模型即可。請注意,任何不在表單域中的屬性都不會包含在內,如果您必須擁有某些東西,請使用HiddenFor。下面我列舉了一個例子。

YourViewModel.cs

public class YourViewModel { 
    public int ExamID { get; set; } 
    public string Name { get; set; } 
    public List<int> QuestionIDs { get; set; } 
    public List<int> AnswerIDs { get; set; } 
} 

YourView.cshtml

@model YourViewModel.cs 
using(Html.BeginForm("PostExam", "YourController", FormMethod.Post)   
{ 
    @Html.HiddenFor(m => m.ExamID) 
    @Html.AntiForgeryToken() 
    <strong>Please enter your name</strong> 
    @Html.TextBoxFor(m => m.Name) 
    @*Your question and answers goes here*@ 
    <input type="submit" value="Hand in" /> 
} 

YourController.cs

public class YourController : Controller 
{ 
    [HttpPost] 
    [ValidateAntiForgeryToken()] 
    public ActionResult PostExam(YourViewModel Submitted) 
    { 
     //Handle submitted data here 
     foreach(var QuestionID in Submitted.QuestionIDs) 
     { 
      //Do something 
     } 
    } 
} 
+0

如果我們討論的是複雜對象而不是基元列表,他需要將集合提交回服務器,這對於初學者來說有點高級。 –

0

使用帶有列表的視圖模型。唯一需要注意,這是綁定到一個列表在某種意義上是一種先進的技術:Model Binding to a List MVC 4

public class Response { 
    public string QuestionId {get;set;} 
    public string AnswerId {get;set;} 
} 

public class ExamViewModel { 
    public int? TestId {get;set;} 
    public List<Response> Responses {get;set;} 
} 

public ActionResult GradeTest(ExamViewModel viewModel) 
{ 
... 
0

我是丁洞。我一直在想這一切都是錯誤的。我查了一下如何將視圖集合傳遞給控制器​​並解決問題!

http://www.c-sharpcorner.com/UploadFile/pmfawas/Asp-Net-mvc-how-to-post-a-collection/

我更新了我的看法/控制器,像這樣:

@foreach (var question in Model.TestQuestions) 
{ 
    @Html.Hidden("Questions[" + questionIndex.ToString() + "].ID", question.ID) 
    <h3>@question.Text</h3> 
    <section> 
     @foreach (var answer in question.TestAnswers) 
     { 
      <div> 
       @Html.RadioButton("Answers[" + questionIndex.ToString() + "].ID", answer.ID) @answer.Text 
      </div> 
     } 
    </section> 
    <hr />   
    questionIndex++;  
} 

和控制器:

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult TestDoGrade(int? testID, IEnumerable<TestQuestion> questions, IEnumerable<TestAnswer> answers) 
    { 
+1

這很好。你可以做的一個改進是創建一個包含ID,問題和答案的「TestViewModel」。然後你將所有東西封裝在一個對象中。 – Jonesopolis

+0

哦,不錯。謝謝!我會去做那件事 – kcabrams

0

您可以接受JObject作爲參數。 JObject它會將隱式表單數據轉換爲您可枚舉的JProperties列表。

JProperty有兩個字段,名稱和值。

相關問題