ASP.NET MVC使用强类型视图模型从视图到控制器保留数据

本文关键字:视图 控制器 保留 数据 模型 ASP MVC 强类型 NET | 更新日期: 2023-09-27 18:06:49

我提前道歉,因为我问了一个以前已经回答过的问题,但我仍然是一个新手,发现很难将解决方案应用到我自己的问题上。

我有一个视图模型,我在创建时填充一些数据,然后打算使用级联下拉列表填充数据(我不能使用任何客户端脚本)

public class StudentPortalModel
{
    public SelectList LocationListModel { get; set; }
    public SelectList ResidenceListModel { get; set; }
    public int ChosenLocation { get; set; }
    public int ChosenBlock { get; set; }
    public int ChosenFlat { get; set; }
    public int ChosenRoom { get; set; }
    public int ChosenResidence { get; set; }
}

我在控制器中有一个动作,它填充了一些列表的视图模型,我使用的下拉菜单,如下所示:

[HttpGet]
        public ActionResult SelectResidence()
        {

            List<Location> objLocationList = (from data in db.Locations select data).ToList();
            SelectList objLocationModelData = new SelectList(objLocationList, "LocationId", "LocationName", 0);

            List<Residence> objResidenceList = (from data in db.Residences select data).ToList();
            SelectList objResidenceModelData = new SelectList(objResidenceList, "ResidenceId", "BlockNumber", 0);

            StudentPortalModel objStudentPortalModel = new StudentPortalModel();
            objStudentPortalModel.LocationListModel = objLocationModelData;
            objStudentPortalModel.ResidenceListModel = objResidenceModelData;

            return View(objStudentPortalModel);
        }

我希望发送给视图的模型数据返回给控制器

 @using (Html.BeginForm("SelectLocation", "StudentPortal", FormMethod.Post))
{
    @Html.DropDownListFor(x => x.ChosenLocation, Model.LocationListModel, "---Select Location---")
    <input type="submit" value="Submit"/>
}

我希望在发送回HttpGet方法时保留我发送给视图的所有数据。

[HttpPost]
        public ActionResult SelectLocation(StudentPortalModel testPortalInstance)
        {
            List<Location> objLocationList = (from data in db.Locations select data).ToList();
            SelectList objLocationModelData = new SelectList(objLocationList, "LocationId", "LocationName", 0);

            List<Residence> objResidenceList = (from data in db.Residences select data).Where(i => i.LocationId == testPortalInstance.ChosenLocation).DistinctBy(x => x.BlockNumber).ToList();
            SelectList objResidenceModelData = new SelectList(objResidenceList, "ResidenceId", "BlockNumber", 0);
            testPortalInstance.LocationListModel = objLocationModelData;
            testPortalInstance.ResidenceListModel = objResidenceModelData;
            return View("SelectResidence", testPortalInstance);
        }

你们可能都知道,唯一被发送回来的数据是ChosenLocation当最终用户从下拉列表中选择它时,它被发送回来,其他的都是空的

本质上,我需要一种方法来保留用户为每个下拉列表选择的选项。这使我能够缩小用户希望选择的房间,直到我能够从表格中破译一个房间并将其分配给用户。

我最大的问题是我似乎找不到我发送给视图的视图模型数据,并将其分配给相同的值发送回来。当我返回到控制器时,一切都是空的,这意味着我必须重新创建数据。

我为我的胡言乱语道歉,我把它归结为我刚编程一个月的事实。

提前感谢您的帮助!

ASP.NET MVC使用强类型视图模型从视图到控制器保留数据

不太清楚为什么你不想使用javascript/jquery(它会提供更好的性能),但你需要将选择的值从相关的POST方法传递给每个GET方法。假设第一步是选择一个位置,然后是住所,那么控制器方法将是

public ActionResult SelectResidence()
{
  List<Location> locations = (from data in db.Locations select data).ToList();
  StudentPortalModel model = new StudentPortalModel()
  {
    LocationListModel = new SelectList(locations, "LocationId", "LocationName")
  }
  return View(model);
}

注意,为ResidenceListModel生成SelectList是没有意义的,因为它没有在第一个视图(

)中使用。
@model StudentPortalModel
@using (Html.BeginForm()) // no need to add parameters
{
  @Html.DropDownListFor(x => x.ChosenLocation, Model.LocationListModel, "---Select Location---")
  <input type="submit" value="Submit"/>
}

将返回到

[HttpPost]
public ActionResult SelectResidence(StudentPortalModel model)
{
  if (!ModelState.IsValid)
  {
    // repopulate locations and return view
  }
  return RedirectToAction("SelectResidence", new { locationID = model.ChosenLocation });
}

将重定向到

public ActionResult SelectResidence(int locationID)
{
  List<Residence> residences = (from data in db.Residences select data).Where(i => i.LocationId == locationID).ToList();
  StudentPortalModel model = new StudentPortalModel()
  {
    ChosenLocation = locationID,
    ResidenceListModel = new SelectList(residences, "ResidenceId", "BlockNumber")
  }
  return View(model);
}

,其视图将为

@model StudentPortalModel
@using (Html.BeginForm())
{
  @Html.HiddenFor(x => x.ChosenLocation)
  @Html.DropDownListFor(x => x.ChosenResidence, Model.ResidenceListModel , "---Select Residence---")
  <input type="submit" value="Submit"/>
}

将返回到

public ActionResult SelectResidence(StudentPortalModel model)
{
  if (!ModelState.IsValid)
  {
    // repopulate residences based on the value of model.ChosenLocation and return view
  }
  // your model now contains values for both ChosenLocation and ChosenResidence 
}

同样,如果你需要去一个视图选择一个房间,你会重定向到(比如)public ActionResult SelectResidence(int locationID, int residenceID)

局部视图,应该使用

@Html.RenderChildAction 

这是你在razor视图中使用的Html Helper上的一个方法。

你的控制器方法应该用(ChildActionOnly)

这是一个属性,使MVC路由操作的方式,它只能通过RenderChildAction调用,这防止人们去到它的url在他们的浏览器。

其次,您应该在级联的每个步骤上将您的模型实例传递给视图。

return Partial(theModel);

或return Partial("somePartialView", theModel);

这些返回将是返回ActionResult类型的控制器动作的示例返回。

最后,表单标记可以将模型传递给回发。MVC将自动JSON序列化它和JSON反序列化它为你,所以不需要有大量的隐藏标签(可能在旧版本的MVC,但我知道这在MVC 4+工作)。

下面是一个局部视图示例:
@model StudentPortalModel
@using (Html.BeginForm("SetSelection", "StudentPortal", new { model = Model}, FormMethod.Post, null))
{
    //Do Form Stuff Here
}

注意,上面我将模型作为路由数据对象传递…MVC会将其序列化为json, post到post data中,然后控制器会自动将其反序列化为model参数,因为它是一个匿名对象,它的model属性和json类型info与控制器动作上的"model"参数名称匹配。

控制器方法示例

[HttpPost]
public ActionResult SetSelection(StudentPortalModel model)
{
    return View("NextCascade", Model)
}    

现在,我没有使用ChildAction只在上面,因为你想要能够发布到这个。[ChildActionOnly]是用来加载你的局部视图的Action,而不是用来返回给它的Action,那些get [HttpPost]。

三个属性一共是:

[ChildActionOnly]
[HttpGet]
[HttpPost] 

你可以在同一个操作上同时使用HttpGet和HttpPost,但这是默认的。换句话说,如果您将所有属性放在一起,它将路由get和post请求。Put如果你只放HttpGet,它不会路由Post请求(你不能向它发送),等等。

现在,我们说PartialView叫做StudentSelection:

控制器上应该有一个父操作,在get请求(第一次加载)时返回它,装饰为[ChildActionOnly]。你应该使用@Html。

post action中的Model应该具有与用户填写的表单中的输入名称相匹配的字段。这允许默认MVC模型绑定将用户选择的值设置为StudentPortalModel中的字段。