繁体   English   中英

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

[英]ASP.NET MVC Retaining Data from View to Controller Using Strongly Typed ViewModel

我事先向您提出一个已经回答过的问题表示歉意,但是我仍然是一个新手,发现很难对自己的问题应用解决方案。

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

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,因为最终用户从下拉列表中选择该数据时会将其发送回去,其他所有内容均为空

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

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

我为我的漫漫长途道歉,我将其归结为我仅编程一个月的事实。

预先感谢您的任何帮助!

尚不清楚为什么您不希望使用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 

这是您在剃刀视图中使用的HTML Helper上的一种方法。

您的控制器方法应使用[ChildActionOnly]装饰

该属性使MVC能够以只能通过RenderChildAction调用该动作的方式来路由该动作,从而防止人们在其浏览器中访问它的url。

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

return Partial(theModel);

或返回Partial(“ somePartialView”,theModel);

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

最后,您的表单标签可以将模型传递给回发。 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数据中,然后控制器将其自动反序列化为model参数,因为它是一个匿名对象,具有模型属性和json类型信息与控制器操作上“模型”参数的名称匹配。

控制器方法示例

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

现在,我不仅在上面使用ChildAction,因为您希望能够发布到此。 [ChildActionOnly]用于加载部分视图的Action,而不适用于将其发布回的操作,这些操作将获得[HttpPost]。

总共三个属性是:

[ChildActionOnly]
[HttpGet]
[HttpPost] 

您可以在同一操作上使用HttpGet和HttpPost,但这是默认设置。 换句话说,如果您一起放弃所有属性,它将路由获取和发布请求。 如果仅放置HttpGet,则放置它,它将不会路由到Post Requests(您不能将其发布到)等。

现在,假设PartialView称为StudentSelection:

控制器上应有一个父操作,该操作最初在以[ChildActionOnly]装饰的get请求(首次加载)上将其返回。 并且您应该使用@ Html.RenderChildAction呈现该操作的局部视图。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM