【问题标题】:ASP.NET MVC Best way to handle dynamic number of parameters in controllerASP.NET MVC 处理控制器中动态参数数量的最佳方法
【发布时间】:2015-01-05 20:40:49
【问题描述】:

我有一个用于考试的视图模型。每个考试都有任意数量的问题。可以是 1 个问题,也可以是 50 个问题。提交后,我需要遍历问题并检查答案。我有一个解决方案,但我觉得这不是最佳做法。

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)

我正在做的事情感觉有点老套。请帮助或让我知道我在正确的轨道上。谢谢!

【问题讨论】:

  • 不要这样做。以正确的方式做事,使用 ViewModel。您正在学习 ASP.NET MVC 的一些核心方面并将它们扔出窗外。它可能会帮助您浏览一些教程
  • 是的,琼斯这样做完全伤害了我。

标签: c# asp.net-mvc action


【解决方案1】:

我真的不了解整个上下文,但如果这是从表单中的视图提交的,那么表单可能是使用 @Html.TextBoxFor 或类似的东西构建的。只需将相同的模型作为 post Action 的输入即可。请注意,任何不在表单字段中的属性都不会被包含在内,如果您必须拥有某些东西,请使用 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
        }
    }
}

【讨论】:

  • 他需要将一个集合提交回服务器,如果我们谈论的是复杂对象列表而不是原始对象,这对于初学者来说有点高级。
【解决方案2】:

使用带有列表的视图模型。唯一需要注意的是绑定到 List 是一种高级技术: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)
{
...

【讨论】:

    【解决方案3】:

    我是个叮当。我想这一切都错了。我查找了如何将集合从视图传递到控制器并解决了问题!

    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)
        {
    

    【讨论】:

    • 那很好。您可以进行的一项改进是创建一个包含其 ID、问题和答案的 TestViewModel。然后您将所有内容封装在一个对象中。
    【解决方案4】:

    您可以接受 JObject 作为参数。 JObject 它将隐藏的表单数据转换为您可以枚举的 JProperties 列表。

    JProperty 有两个字段,名称和值。

    【讨论】:

      猜你喜欢
      • 2016-01-24
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多