【问题标题】:MVC, passing classes between controller and viewMVC,在控制器和视图之间传递类
【发布时间】:2012-10-08 20:56:21
【问题描述】:

我有一个场景如下; “调查”包含“问题”类型的列表; “问题”由一个 id 和一个名为“文本”的字符串组成。以下是类定义:

public class Survey
{
    public int SurveyId { get; set; }
    public string Title { get; set; }
    public List<Question> Questions { get; set; }

    public Survey()
    {
        this.Questions = new List<Question>();
    }
}

public class Question
{
    public int QuestionId { get; set; }
    public string QuestionText { get; set; }
    public int OwningSurveyId { get; set; }
}

我希望能够从特定调查的页面链接以创建一个新问题(可以正常工作),但是当提交问题表单时,我想做两件事; 1) 确保正确设置了 OwningSurveyId,2) 将问题添加到 Survey.Questions List。

我愿意接受任何获得此功能的解决方案 - 我采用的方法可能不是最好的。我决定做的是将调查对象传递给问题的创建表单,以便在提交表单时,表单包含两个对象,因此我可以正确执行上述两个任务(1 和 2)。

我在 QuestionController 中设置 Create Question 页面如下:

// GET: /Question/Create

    public ActionResult Create(Survey OwningSurvey)
    {
        return View(OwningPulse);
    }

[HttpPost]
    public ActionResult Create(Pulse OwningPulse, Question NewQuestion)
    {
        ModelState["OwningSurveyId"].Errors.Clear();

        if (ModelState.IsValid)
        {
            OwningPulse.Questions.Add(NewQuestion);
            db.Questions.Add(NewQuestion);
            db.SaveChanges();
            return RedirectToAction("Index", "Survey");
        }

        return View(OwningSurvey);
    }

并且该问题的 Create.cshtml 文件具有以下内容:

@model MoodTool.Interface.Models.Survey

@{
ViewBag.Title = "Create";

var Question = new MoodTool.Interface.Models.Question();
Question.OwningPulseId = Model.SurveyId;
}

@using (Html.BeginForm("Create", "Question", "{NewQuestion}", FormMethod.Post, new { NewQuestion = Question }))
{... code follows

我遇到的问题是 .cshtml 文件中“模型”的值为空,因此页面崩溃。 Question 控制器(“GET”版本)的 Create 方法中的 OwningSurvey 的值也为 null。

谁能指引我正确的方向?我意识到我可能在做一些严重错误的事情(设计模式),或者犯了一个简单的语法错误,但我是 MVC 的新手并且在循环中。

谢谢

【问题讨论】:

    标签: asp.net-mvc-3


    【解决方案1】:

    您是否正在为在调查操作中添加问题的调查加载模型?如果不是,那么这就是您的模型为空的原因。这只是我根据我在这里看到的猜测。 RedirectToActions 不加载模型,因此您必须将其放入 TempData 并在重定向操作中重新加载。

    第二部分

    在第一部分中,您将创建问题并重定向到调查的索引操作。

     OwningPulse.Questions.Add(NewQuestion);
     db.Questions.Add(NewQuestion);
     db.SaveChanges();
     return RedirectToAction("Index", "Survey");
    

    在索引操作中,您需要重新加载最初放置问题的调查并将其加载到模型中以传递给视图。使用上面的 lavriks 方法,通过将 id 传递给 action 方法,您可以从数据库中获取该调查并将其传递给为视图定义的模型中的视图。

        public ActionResult Index(int id)
        {
             // assuming you have some built in functionality to retrieve the survey information from the db through the constructor given an id
            Survey s1 = new survey(id);  
    
            // some of this is pseudo code, assumes you have a model defined called survey for the view using it
            // Return view with model.
            return View( "Survey" , s1 );
        }
    

    当我谈到 tempdata 而不是将 ID 传递给 action 方法并在 action 方法中为您的视图再次查找它时,您可以将对象存储在 tempdata 中

         // save data to survey in teh create action method
         TempData["survey"] = survey
    

    然后在调查的默认索引操作方法中,从临时数据中调用调查并将其发送到视图。

         Survey s1 = (Survey)Tempdata["survey"];
         return View ("Survey", s1);
    

    同样,其中一些是伪代码,并不完全完整,但它应该为您指明正确的方向。这两种方法都有其优点和缺点,但取决于应用程序、对象的大小、有多少人正在访问页面等,您可以选择其中一个或。

    【讨论】:

    • 感谢您的评论。恐怕我不明白;你介意扩大你的答案吗?
    • 感谢您的澄清,这种方法(TempData)已经解决了我的问题。谢谢!
    【解决方案2】:

    这里最好的方法之一是 Post-Redirect-Get 模式。您只需发布带有调查 ID 的问题表单。在控制器中,您可以尝试按 id 读取调查并检查它是否存在。然后添加问题并保存调查。例如,重定向到 Survey GET 操作。它将显示包括新添加的问题。 此外,您将仅在此处发布问题和调查 ID - 您不再需要任何内容​​。您不会通过发布一些不必要的数据来更改调查 - 所以它也更安全一些。

    编辑。

    例如。

    // GET: /Question/Create
    public ActionResult Create(int surveyId)
    {
        return View(new Question(){OwningSurveyId = surveyId });
    }
    [HttpPost]
    public ActionResult Create(Question newQuestion)
    {
        if (ModelState.IsValid)
        {
            //I've never used EntityFramework so just a pseudo code here
            var survey = db.Surveys.Get(newQuestion.OwningSurveyId);
            if(survey != null)
            {
                survey.Questions.Add(newQuestion);
                db.Surveys.Save(survey); 
                db.SaveChanges();
                //If you want to open specific survey, 
                //you can pass it's Id to read it in Survey index action
                return RedirectToAction("Index", "Survey", {Id = survey.Id});
            }
        }
    
        return View(newQuestion);
    }
    

    并查看创建问题

    @model MoodTool.Interface.Models.Question
    
    @{
    ViewBag.Title = "Create";
    }
    
    @using (Html.BeginForm("Create", "Question", FormMethod.Post))
    {
         @Html.HiddenFor(x => x.OwningSurveyId)
         @Html.EditorFor(x => x.QuestionText)
           //etc.
     }
    

    【讨论】:

    • 感谢您的评论。我已经在 Create 方法中使用了“RedirectToAction”;你能举例说明我如何使用 PRG 模式来解决这个问题吗?谢谢
    • 太好了,谢谢。我也试过你的方法,效果很好!我选择了 TempData,因为它仍然存在,我以后可以使用它,但你确实解决了这个问题,所以我很难过我不能把它们都作为答案:-)
    猜你喜欢
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    相关资源
    最近更新 更多