C# 在mvc中使用动作之间的值查看模型

C# 在mvc中使用动作之间的值查看模型,c#,asp.net-mvc,C#,Asp.net Mvc,我有个问题,我想不出怎么解决。请注意,我对MVC非常陌生 我正在设计一个有8个问题的调查。我在视图中创建每个问题 我需要的是在视图之间保留数据,但是即使我将它们作为单个视图模型传递,我也会丢失数据 请帮忙 我有下面的视图模型 public class SurveyViewModelNew { public string description { get; set; } public Question1ViewM

我有个问题,我想不出怎么解决。请注意,我对MVC非常陌生

我正在设计一个有8个问题的调查。我在视图中创建每个问题

我需要的是在视图之间保留数据,但是即使我将它们作为单个视图模型传递,我也会丢失数据

请帮忙

我有下面的视图模型

 public class SurveyViewModelNew
        {        
            public string description { get; set; }

            public Question1ViewModel QuestionText1 { get; set; }
            public Question2ViewModel QuestionText2 { get; set; }
            public Question3ViewModel QuestionText3 { get; set; }
            public Question4ViewModel QuestionText4 { get; set; }
            public Question5ViewModel QuestionText5 { get; set; }
            public Question6ViewModel QuestionText6 { get; set; }
            public Question7ViewModel QuestionText7 { get; set; }
            public Question8ViewModel QuestionText8 { get; set; }
        }
以及每个问题的视图模型:

  public class Question1ViewModel
        {
            public string QuestionText { get; set; }
            public AnswerViewModel Answers { get; set; }
        }
我的观点是什么样的

 @model survey.Models.SurveyViewModelNew

   @using (Html.BeginForm("QuestionOneNext", "CreateSurveyStep2", FormMethod.Post, new { @class = "form-horizontal", role = "form", Model = Model }))

   {

        <div class="form-horizontal">

            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })

            <div class="form-group">
                @Html.Label("Question 1: What question would you like to ask", htmlAttributes: new { @class = "control-label col-md-4" })
                <div class="col-md-5">
                    @Html.EditorFor(model => model.QuestionText1.QuestionText, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.QuestionText, "", new { @class = "text-danger" })
                </div>
            </div>
            <br/>
            <br/>          
            <div class="form-group">
                @Html.Label("Answer A", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextA, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextA, "", new { @class = "text-danger" })
                </div>
            </div>    
            <div class="form-group">
                @Html.Label("Answer B", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextB, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextB, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer C", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextC, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextC, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer D", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextD, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextD, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer E", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextE, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextE, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer F", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextF, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextF, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer G", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextG, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextG, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.Label("Answer H", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.QuestionText1.Answers.AnswerTextH, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.QuestionText1.Answers.AnswerTextH, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer K", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                   @Html.Label("Not applicable", htmlAttributes: new { @class = "control-label col-md-2" })
                </div>
            </div>
            <div class="form-group">
                @Html.Label("Answer L", htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                   @Html.Label("Flag inappropriate question/refuse to answer", htmlAttributes: new { @class = "control-label col-md-5" })
                </div>
            </div>
                  <br/>
            <br/>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Previous Step" class="btn btn-info" name="direction"/>
                    <input type="submit" value="Add a New Question to this survey" class="btn btn-danger" name="direction" />
                    <input type="submit" value="Countinue to submit this survey" class="btn btn-success" name="direction" />
                  </div>
            </div>
        </div>
    }
当我在控制器中遇到问题2动作时,我就失去了第一个问题的答案

我使用TemData修复了此问题,以下是我的固定控制器:

 [HttpGet]
    public ActionResult QuestionOne(SurveyViewModelNew surveyViewModel)
    {
        var currentSurveyViewModel = (SurveyViewModelNew)TempData["SurveyView"];

        if (currentSurveyViewModel != null)
        {
            if (currentSurveyViewModel.description != null)
            {
                surveyViewModel.description = currentSurveyViewModel.description;
            }

            if (currentSurveyViewModel.QuestionText1 != null)
            {
                surveyViewModel.QuestionText1 = currentSurveyViewModel.QuestionText1;
            }
            if (currentSurveyViewModel.QuestionText2 != null)
            {
                surveyViewModel.QuestionText2 = currentSurveyViewModel.QuestionText2;
            }
            if (currentSurveyViewModel.QuestionText3 != null)
            {
                surveyViewModel.QuestionText3 = currentSurveyViewModel.QuestionText3;
            }
            if (currentSurveyViewModel.QuestionText4 != null)
            {
                surveyViewModel.QuestionText4 = currentSurveyViewModel.QuestionText4;
            }
            if (currentSurveyViewModel.QuestionText5 != null)
            {
                surveyViewModel.QuestionText5 = currentSurveyViewModel.QuestionText5;
            }
            if (currentSurveyViewModel.QuestionText6 != null)
            {
                surveyViewModel.QuestionText6 = currentSurveyViewModel.QuestionText6;
            }
            if (currentSurveyViewModel.QuestionText7 != null)
            {
                surveyViewModel.QuestionText7 = currentSurveyViewModel.QuestionText7;
            }

            TempData["SurveyView"] = surveyViewModel;
        }

        if (surveyViewModel.description!= null)
        {
            surveyViewModel.description = surveyViewModel.description;
            TempData["SurveyView"] = surveyViewModel;
        }
        return View("QuestionOne", surveyViewModel);
    }

    [HttpGet]
    public ActionResult QuestionOneNext(SurveyViewModelNew surveyViewModel, string direction)
    {
        var currentSurveyViewModel = (SurveyViewModelNew)TempData["SurveyView"];
        if (currentSurveyViewModel != null)
        {
            if (currentSurveyViewModel.description != null)
            {
                surveyViewModel.description = currentSurveyViewModel.description;
            }
            if (currentSurveyViewModel.QuestionText1 != null)
            {
                surveyViewModel.QuestionText1 = currentSurveyViewModel.QuestionText1;
            }
            if (currentSurveyViewModel.QuestionText2 != null)
            {
                surveyViewModel.QuestionText2 = currentSurveyViewModel.QuestionText2;
            }
            if (currentSurveyViewModel.QuestionText3 != null)
            {
                surveyViewModel.QuestionText3 = currentSurveyViewModel.QuestionText3;
            }
            if (currentSurveyViewModel.QuestionText4 != null)
            {
                surveyViewModel.QuestionText4 = currentSurveyViewModel.QuestionText4;
            }
            if (currentSurveyViewModel.QuestionText5 != null)
            {
                surveyViewModel.QuestionText5 = currentSurveyViewModel.QuestionText5;
            }
            if (currentSurveyViewModel.QuestionText6 != null)
            {
                surveyViewModel.QuestionText6 = currentSurveyViewModel.QuestionText6;
            }
            if (currentSurveyViewModel.QuestionText7 != null)
            {
                surveyViewModel.QuestionText7 = currentSurveyViewModel.QuestionText7;
            }
        }
        if (direction == "Countinue to submit this survey")
            return View("something", surveyViewModel);

        else if (direction == "Add a New Question to this survey")
        {
            TempData["SurveyView"] = surveyViewModel;
            return View("QuestionTwo", surveyViewModel);                 
        }                                     

        else if (direction == "Previous Step")
        {
            TempData["SurveyView"] = surveyViewModel;
            return View("Index", surveyViewModel);
        }
        else return View();
    }

要将完整的模型从一个页面传递到下一个页面,您必须确保模型的所有属性都是表单的一部分,并且在每次表单提交操作中都会回发到服务器


要实现这一点,您需要在视图中使用@HTML.HiddenFor创建隐藏表单字段,该字段包含模型的所有数据,即使您没有在特定页面上向用户显示这些数据。

每次发出同步HTTP请求时,您实际上都在重新加载同一页面,只是返回了不同的值。如果希望数据持久化,您将受益于了解更多关于异步请求的信息,AJAX可以无需重定向就发送/接收信息……否则您需要保留问题1的答案并将其与问题2的视图一起返回……然后对于问题3,您需要确保问题1和2被保留,并将其值与问题3的背景

你可以像前面提到的那样隐藏领域,但是你应该认为这是一个学习新事物和有用东西的机会。利用隐藏字段已经过时了。选项1:TempData

这里也讨论了同样的问题:

问题在于您对RedirectToAction的使用。不能以这种方式传递模型,只能传递基元类型。您需要在此过程中使用TempData:

[HttpPost]
public ActionResult QuestionOneNext(SurveyViewModelNew surveyViewModel, string direction)
{
    var currentSurveyViewModel = surveyViewModel ?? (SurveyViewModel)TempData["SurveyView"];
    if (direction == "Countinue to submit this survey")
    {
        TempData["SurveyView"] = currentSurveyViewModel;
        return RedirectToAction("Edit", "something", null);
    }

    if (direction == "Add a New Question to this survey")

    {
        return View("QuestionTwo", currentSurveyViewModel);
        //return RedirectToAction("QuestionTwo", "CreateSurveyStep2", surveyViewModel);
    }
    if (direction == "Previous Step")
    {
        TempData["SurveyView"] = currentSurveyViewModel;
        return RedirectToAction("Index", "CreateSurveyStep1", null);
    }

    return View();
}

[HttpPost]
public ActionResult QuestionTwo(SurveyViewModelNew surveyViewModel, string direction)
{
    var currentSurveyViewModel = surveyViewModel ?? (SurveyViewModel)TempData["SurveyView"];
    if (direction == "Countinue to submit this survey")
    {
        TempData["SurveyView"] = currentSurveyViewModel ;
        return RedirectToAction("Edit", "NutStorage", null);
    }

    if (direction == "Add a New Question to this survey")
    {
        //return RedirectToAction("QuestionThree", "CreateSurveyStep2", surveyViewModel);
        return View("QuestionThree", "CreateSurveyStep2", currentSurveyViewModel );
    }
    if (direction == "Previous Step")
    {
        TempData["SurveyView"] = currentSurveyViewModel ;
        return RedirectToAction("QuestionOne", "CreateSurveyStep2", null);
    }

    return View();
}
选项2:RouteValueDictionary

使用复杂类型还有另一种选择,那就是使用RouteValueDictionary。这在这个非常类似的问题中涉及:

重定向到操作调用的总体思路是:

return RedirectToAction("Edit", "NutStorage", new RouteValueDictionary(surveyViewModel));

与以这种方式对抗MVC框架不同的是,这里有一些其他的方法可以让你做得更有意义

1请考虑在进入数据库时保存答案

该记录可能是某种临时记录,直到用户最终提交问卷时才被认为是真实的


2如果问题数据不太大,则将其自身部分中的每个问题呈现为div,一个视图中的选项卡控件,并在单击按钮时处理javascript部分之间的切换。您可以使用现有的ViewModel将所有问题带入视图,并在最后发布和保存所有问题。让它成为一个问题列表,而不是8个问题属性,您甚至可以在视图中有一个for循环,为每个问题呈现一个partial。分部可以处理“下一个”和“上一个”按钮等。

可能重复的模型必须将模型保存到存储库中,然后用重定向到的方法再次检索。这当然是处理OP整体架构的有效方法,但不回答重定向到其他操作时模型参数为null的原因。确实如此…页面将刷新,用户的答案将被删除。DOP使用:return RedirectToActionEdit、NutStorage、surveyViewModel;在他们的第一个控制器动作中,模型在这里是满的。但是,当它开始编辑操作时,页面还没有刷新,因为它还没有返回到客户端。问题在于通过RedirectToAction传递完整模型,我为什么将其标记为重复,相关问题在注释中。我认为OP能够将模型返回到第一个操作,但尝试重定向,并且在重定向中获得空模型。感谢您的回答。你的意思是我需要将这个:@Html.HiddenFormodel=>Model添加到我的第二个视图中吗?不幸的是,它没有那么简单。就像您必须为每个属性执行Html.editor一样,您也必须为其他属性执行Html.HiddenFor。e、 g.Html.HiddenFormodel=>model.QuestionText2.QuestionText等。更好的设计可能是在数据库中维护问题,并将问题编号作为查询字符串传递。然后,控制器可以从数据库中检索问题,并使用更简单的模型显示它。这并不能解决OP的问题。他们的表单将提交给第一个操作,QuestionNext和一个包含数据的模型。他们正在尝试“RedirectToAction”,该操作正在传递一个空模型。这是由于不正确使用RedirectToAction造成的。Jason,谢谢你的评论。有希望地
OP可以使用RedirectToAction修复此问题。我知道我的回答并没有解决OP的问题,正如你在第一条评论中已经说明的那样。我刚才回答了他关于如何使用Html.HiddenFor的问题。第二个选项不起作用,因为从复杂对象内部创建新的RouteValueDictionary会调用每个属性的ToString方法。由于OP的模型包含复杂对象的属性,路由值将是QuestionText1=someAssembly.Question1ViewModel,即无法绑定到复杂对象的字符串,绑定将失败属性wil;不要为空,TempData不是一个好的解决方案。如果使用刷新浏览器,数据将丢失。@StephenMuecke TempData仅在一个请求中有效。因此,在本例中,用户正在做一些事情并单击submit。web服务器正在从原始操作重定向。我认为TempData在这种情况下是非常合适的,但是,我提供了一个备用方案,我相信大多数人都会觉得这两个方案更好。感谢您的回答,我现在将尝试您的建议,并让您知道@JasonWilczakI按照您的建议使用TempData解决了我的问题。但我需要编写大量代码,因此每次用户单击“上一个”或“下一个”时,我都会将更新的数据保存在TemData中。我把我的代码贴在问题上,这样你就可以知道我做了什么@贾森威尔扎克
return RedirectToAction("Edit", "NutStorage", new RouteValueDictionary(surveyViewModel));