mvc提交后没有ActionResult方法中的数据

时间:2022-10-22 11:24:50

I have an Index page on which there is a section to write a project name and select from a dropdownlist a project type.

我有一个索引页面,其中有一个部分用于编写项目名称,并从下拉列表中选择项目类型。

Below that I have a submit button that directs to the ActionResult method Create in the Projects controller.

下面我有一个提交按钮,指向在Projects控制器中的ActionResult方法Create。

Code: [UPDATE] index.cshtml:

代码:[UPDATE] index.cshtml:

@using reqcoll.ViewModels
@model myViewModel

@{
  ViewBag.Title = "ReqColl - project";
}

@* First half *@
@using (Html.BeginForm("CreateProject", "Projects"))
{
  @Html.AntiForgeryToken()

  <div class="top-spacing col-md-12 col-lg-12 col-sm-12">
    @RenderTopHalf(Model.modelProject)
  </div>
}


@* Second half *@
@using (Html.BeginForm("CreateRequirement", "Projects"))
{
  @Html.AntiForgeryToken()

  <div class="form-group" id="pnSecondHalf">
    @* Requirements list *@
    <div class=" col-md-6 col-lg-6 col-sm-12">
      @RenderBottomLeftHalf(Model.modelRequirement)
    </div>

    @* New/Edit requirements panel *@
    <div class="col-md-6 col-lg-6 col-sm-12">
      @RenderBottomRightHalf(Model.modelRequirement)
    </div>
  </div>
}

@*     ================================================================================= ============= *@
@* Helpers *@

@helper RenderTopHalf(reqcoll.Models.Project project)
    {
  <div class=" well">
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="row">
      @Html.LabelFor(model => project.projectName, htmlAttributes: new { @class =     "control-label col-md-2 col-lg-2 col-sm-12" })
      <div class="col-md-10 col-lg-10 col-sm-12">
        @Html.TextBoxFor(model => project.projectName, htmlAttributes: new {   @class = "ProjectNameInput" })
        @Html.ValidationMessageFor(model => project.projectName)
      </div>
    </div>
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="row row-spacing">
      @Html.LabelFor(model => project.projectType, htmlAttributes: new { @class = "control-label col-md-2 col-lg-2 col-sm-12" })
      <div class="col-md-10 col-lg-10 col-sm-12">
        @Html.DropDownListFor(model => project.projectType, new SelectList(
              new List<Object>{
                       new { value = 0 , text = "...Select..." },
                       new { value = 1 , text = "Windows application" },
                       new { value = 2 , text = "Web application" },
                       new { value = 3 , text = "Device application"}
                },
              "value",
              "text",
               project.projectType), htmlAttributes: new { @class =    "DropDownList" })
        @Html.ValidationMessageFor(model => project.projectType)
      </div>
      <input type="hidden" value="" id="hdProjectID" />
    </div>
    <div class="row top-spacing col-md-offset-5 col-sm-offset-5">
      <div id="pnCreate" class=" col-sm-4 col-md-4 col-lg-4">
        <input type="submit" class="btn btn-default" value="Create" />
      </div>
      <div id="pnEdit" class=" col-sm-4 col-md-4 col-lg-4">
        <input type="submit" class="btn btn-default" value="Edit" />
        |
        <input type="submit" class="btn btn-default" value="Delete" />
      </div>
    </div>
  </div>
}

@helper RenderBottomLeftHalf(reqcoll.Models.Requirement requirement)
    {
  <div class=" well">
    <table class="table">
      <tr>
        <th>
          @if (Model.modelProject.Requirements != null)
          {
            var m = Model.modelProject;
            if (m.Requirements.Count > 0)
            {
              @Html.DisplayNameFor(model =>  model.modelProject.Requirements[0].shortDesc)
            }
          }
          else
          {
            <label class="label label-primary col-sm-12 col-md-6 col-lg-6">No requirements available</label>
          }
        </th>
        <th></th>
      </tr>
      @if (Model.modelProject.Requirements != null)
      {
        var m = Model.modelProject;
        if (m.Requirements.Count > 0)
        {
          foreach (var item in Model.modelProject.Requirements)
          {
            <tr>
              <td>
                @Html.DisplayFor(modelItem => item.shortDesc)
              </td>
              <td>

                @* buttons here*@

                @*@Html.ActionLink("E", "Edit", new { id = item.requirementID })     |
                  @Html.ActionLink("D", "Delete", new { id = item.requirementID     })*@
              </td>
            </tr>
          }
        }
      }
    </table>
  </div>
}



 @helper RenderBottomRightHalf(reqcoll.Models.Requirement requirement)
    {
  <div class=" well">
    @Html.ValidationSummary(true)
    <div class="row">
      @Html.LabelFor(model => requirement.shortDesc, htmlAttributes: new { @class = "control-label col-md-4 col-lg-4 col-sm-12" })
      <div class="col-md-8 col-lg-8 col-sm-12">
        @Html.TextBoxFor(model => requirement.shortDesc, htmlAttributes: new { @class = "RequirementShortDesc" })
        @Html.ValidationMessageFor(model => requirement.shortDesc)
      </div>
    </div>
    @Html.ValidationSummary(true)
    <div class="row row-spacing">
      @Html.LabelFor(model => requirement.longDesc, htmlAttributes: new { @class = "control-label col-md-4 col-lg-4 col-sm-12" })
      <div class="col-md-8 col-lg-8 col-sm-12 RequirementLongDesc">
        @Html.EditorFor(model => requirement.longDesc)
        @Html.ValidationMessageFor(model => requirement.longDesc)
      </div>
    </div>
    @Html.ValidationSummary(true)
    <div class="row row-spacing">
      @Html.LabelFor(model => requirement.priorityCode, htmlAttributes: new { @class = "control-label col-md-4 col-lg-4 col-sm-12" })
      <div class="col-md-8 col-lg-8 col-sm-12">

        @foreach (var value in Enum.GetValues(requirement.priorityCode.GetType()))
        {
          <div class="control-label col-sm-5 col-md-5 col-lg-5">
            @Html.RadioButtonFor(m => requirement.priorityCode, value)
            @Html.Label(value.ToString())
          </div>
        }


        @Html.ValidationMessageFor(model => requirement.priorityCode)
      </div>
    </div>
    <input type="hidden" value="" id="hdRequirementID" />

    <div class="row top-spacing col-md-offset-5 col-sm-offset-5">
      <div id="pnReqCreate" class=" col-sm-12 col-md-6 col-lg-6">

        @* submit button here *@
        @*@Html.ActionLink("Add", "Add", "Requirement", new { @class = "btn btn-default btnSize" })*@
      </div>
      <div id="pnReqEdit" class=" col-sm-12 col-md-6 col-lg-6">
        @* submit buttons here *@
        @*@Html.ActionLink("Edit", "Edit", "Requirement", new { @class = "btn btn-default btnSize" })
          @Html.ActionLink("Delete", "Delete", "Requirement", new { @class = "btn btn-default btnSize" })*@
      </div>
    </div>
  </div>
}





@section Scripts {
  <script>

    $(function () {

      var pID = $('#hdProjectID').val();

      if (pID != null) {
        if (pID.length > 0) {
          $('#pnEdit').show();
          $('#pnCreate').hide();
          $('#pnSecondHalf').show();
        } else {
          $('#pnEdit').hide();
          $('#pnCreate').show();
          $('#pnSecondHalf').hide();
        }
      } else {
        $('#pnEdit').hide();
        $('#pnCreate').show();
        $('#pnSecondHalf').hide();
      }

      var rID = $('#hdRequirementID').val();

      if (rID != null) {
        if (rID.length > 0) {
          $('#pnReqEdit').show();
          $('#pnReqCreate').hide();
        } else {
          $('#pnReqEdit').hide();
          $('#pnReqCreate').show();
        }
      } else {
        $('#pnReqEdit').hide();
        $('#pnReqCreate').show();
      }

    });

  </script>

  @Scripts.Render("~/bundles/jqueryval")
}

ViewModel:

using reqcoll.Models;

namespace reqcoll.ViewModels
{
  public class myViewModel
  {
    public Project modelProject;
    public Requirement modelRequirement;

  }
}

Controller:

using System.Web.Mvc;
using reqcoll.Models;
using reqcoll.ViewModels;

namespace reqcoll.Controllers
{
  public class ProjectsController : Controller
  {
    private myContext db = new myContext();

    // GET: Projects
    public ActionResult Index()
    {
      // allow more than one model to be used in the view

      var vm = new myViewModel()
      {
        modelProject = new Project() { projectName = "test", projectType = 1 },
        modelRequirement = new Requirement() { requirementID = -1 },
      };

      return View(vm);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult CreateProject(myViewModel vm)
    {
      if (vm != null)
      {
        var ab = Request.Form;

        // key 1: __RequestVerificationToken
        // key 2: project.projectName
        // key 3: project.projectType


        if (ModelState.IsValid)
        {
          Project project = vm.modelProject;

          // db.Project.Add(project.Item1);
          //  db.SaveChanges();
          // return RedirectToAction("Index");
        }
      }
      return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        db.Dispose();
      }
      base.Dispose(disposing);
    }

  }
}

[ORIGINAL]

@using (Html.BeginForm("Create", "Projects"))
{
  @Html.AntiForgeryToken()

  <div class="top-spacing col-md-12 col-lg-12 col-sm-12">
    <div class=" well">
      @Html.ValidationSummary(true)
      <div class="row">
        @Html.LabelFor(model => model.Item1.projectName, htmlAttributes: new { @class = "control-label col-md-2 col-lg-2 col-sm-12" })
        <div class="col-md-10 col-lg-10 col-sm-12">
          @Html.TextBoxFor(model => model.Item1.projectName, htmlAttributes: new { @class = "ProjectNameInput" })
          @Html.ValidationMessageFor(model => model.Item1.projectName)
        </div>
      </div>
      @Html.ValidationSummary(true)
      <div class="row row-spacing">
        @Html.LabelFor(model => model.Item1.projectType, htmlAttributes: new { @class = "control-label col-md-2 col-lg-2 col-sm-12" })
        <div class="col-md-10 col-lg-10 col-sm-12">
          @Html.DropDownListFor(model => model.Item1.projectType, new  SelectList(
              new List<Object>{
                       new { value = 0 , text = "...Select..."  },
                       new { value = 1 , text = "Windows application"  },
                       new { value = 2 , text = "Web application" },
                       new { value = 3 , text = "Device application"}
                },
              "value",
              "text",
               0), htmlAttributes: new { @class = "DropDownList" })
          @Html.ValidationMessageFor(model => model.Item1.projectType)
        </div>
        <input type="hidden" value="" id="hdProjectID" />
      </div>
      <div class="row top-spacing col-md-offset-5 col-sm-offset-5">
        <div id="pnCreate" class=" col-sm-4 col-md-4 col-lg-4">
          <input type="submit" class="btn btn-default" value="Create" />
        </div>
        <div id="pnEdit" class=" col-sm-4 col-md-4 col-lg-4">

          <input type="submit" class="btn btn-default" value="Edit" />
          |
          <input type="submit" class="btn btn-default" value="Delete" />
        </div>
      </div>
    </div>
  </div>
}

ProjectsController:

 private myContext db = new myContext();

 // GET: Projects
 public ActionResult Index()
 {
   // allow more than one model to be used in the view
   return View(new Tuple<Project, Requirement, Priority>(new Project(), new Requirement(), new Priority()));
 }

 [HttpPost]
 [ValidateAntiForgeryToken]
 [AcceptVerbs(HttpVerbs.Post)]
 public ActionResult Create([Bind(Include = "projectName,projectType")] Project project)
 {
   if (ModelState.IsValid)
   {
     db.Project.Add(project);
     db.SaveChanges();
     return RedirectToAction("Index");
   }

   return RedirectToAction("Index");
 }

So when the submit button is clicked, the ActionResult Create is called, but the ModelState is not valid and does not have the information enterd by the user.

因此,单击提交按钮时,将调用ActionResult Create,但ModelState无效,并且没有用户输入的信息。

What am I doing wrong?

我究竟做错了什么?

3 个解决方案

#1


1  

Your model is looking like complex object as you are using model.Item1.projectName and model.Item1.projectType, but in action method you are trying to get values directly which is wrong.

当您使用model.Item1.projectName和model.Item1.projectType时,您的模型看起来像复杂的对象,但在操作方法中,您试图直接获取值,这是错误的。

#2


1  

[Updated code]

With the new code posted, this quick correction to your model will allow it to bind correctly from your view:

发布新代码后,对模型的快速更正将允许它从您的视图中正确绑定:

namespace reqcoll.ViewModels
{
  public class myViewModel
  {
    public Project project;
    public Requirement requirement;

  }
}

[Original]

Despite the fact of using a Tuple<> type instead of defining a class that would encapsulate the data to pass to the view. You can still achieve what you want by creating a helper in your view.

尽管使用Tuple <>类型而不是定义一个类来封装要传递给视图的数据。您仍然可以通过在视图中创建帮助程序来实现所需的功能。

@helper RenderMyProject(Project project) {
    ...
    @Html.TextBoxFor(x=> project.projectType)
    ...
}

Then, you will call this helper

然后,您将调用此帮助程序

@RenderMyProject(model.Item1)

Whats the difference?

有什么不同?

The name of the input will change. Instead of posting [Item1.projectType] Inside the response object to your controller, it will look like [project.projectType] which will be mapped to your project parameter automatically.

输入的名称将更改。而不是将[Item1.projectType]发布到响应对象内部,它将看起来像[project.projectType],它将自动映射到您的项目参数。

#3


0  

Found the problem.

发现了问题。

I added {get; set;} in the myViewModel to both the models and then it worked.

我加了{get;在myViewModel中设置;}到两个模型然后它工作。

so:

using reqcoll.Models;

namespace reqcoll.ViewModels
{
  public class myViewModel
  {
    public Project Project { get; set; }
    public Requirement Requirement { get; set; }

  }
}

#1


1  

Your model is looking like complex object as you are using model.Item1.projectName and model.Item1.projectType, but in action method you are trying to get values directly which is wrong.

当您使用model.Item1.projectName和model.Item1.projectType时,您的模型看起来像复杂的对象,但在操作方法中,您试图直接获取值,这是错误的。

#2


1  

[Updated code]

With the new code posted, this quick correction to your model will allow it to bind correctly from your view:

发布新代码后,对模型的快速更正将允许它从您的视图中正确绑定:

namespace reqcoll.ViewModels
{
  public class myViewModel
  {
    public Project project;
    public Requirement requirement;

  }
}

[Original]

Despite the fact of using a Tuple<> type instead of defining a class that would encapsulate the data to pass to the view. You can still achieve what you want by creating a helper in your view.

尽管使用Tuple <>类型而不是定义一个类来封装要传递给视图的数据。您仍然可以通过在视图中创建帮助程序来实现所需的功能。

@helper RenderMyProject(Project project) {
    ...
    @Html.TextBoxFor(x=> project.projectType)
    ...
}

Then, you will call this helper

然后,您将调用此帮助程序

@RenderMyProject(model.Item1)

Whats the difference?

有什么不同?

The name of the input will change. Instead of posting [Item1.projectType] Inside the response object to your controller, it will look like [project.projectType] which will be mapped to your project parameter automatically.

输入的名称将更改。而不是将[Item1.projectType]发布到响应对象内部,它将看起来像[project.projectType],它将自动映射到您的项目参数。

#3


0  

Found the problem.

发现了问题。

I added {get; set;} in the myViewModel to both the models and then it worked.

我加了{get;在myViewModel中设置;}到两个模型然后它工作。

so:

using reqcoll.Models;

namespace reqcoll.ViewModels
{
  public class myViewModel
  {
    public Project Project { get; set; }
    public Requirement Requirement { get; set; }

  }
}