繁体   English   中英

我如何将现有模型(设备)数据附加到MVC ASP.NET中的另一个模型(用户)数据

[英]How can i attach existing model(device) data to another model(user) data in mvc asp.net

我正在创建一个系统,在该系统中,创建用户时可以将设备分配给该用户。 我正在使用一个下拉列表来执行此操作,并且在下拉列表中填充了设备列表时,它不会使用该设备更新用户。 多个用户可以使用同一设备,并且我想避免进行硬编码,因为该信息已经在数据库中。

我首先通过ef代码执行此操作,其他任何建议都将被考虑在内。 我真的只是专注于使它起作用,所以我愿意提出建议。 我也想让它与Edit一起工作,但是如果我使用类似的代码,我想解决方案将同时解决创建和编辑问题。

我一直在使用viewmodel在索引页面上显示设备。 db上的当前用户显示了他们分配的设备,因此我知道这是可行的,但是我不得不在表数据中手动分配设备。

PatientController.cs(用户也称为患者)

namespace FaceToFaceWebsite.Controllers
{
    public class PatientController : Controller
    {
        private F2FData db = new F2FData();

        public ActionResult Index()
        {
            var viewModel = db.Users
                .Select(u => new UserDeviceViewModel() 
            { 
                User = u,
                Device = u.Device

             }).ToList();

            return View(viewModel);
        }


        public ActionResult Create()
        {
            ViewBag.DeviceID = new SelectList(db.Devices, "DeviceID", "Name");

            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "UserID,CodeName,UseBriefInstructions,DeviceID,Name")] User user, Device device)
        {
            if (ModelState.IsValid)
            {

                db.Users.Add(user);
                db.Devices.Attach(device);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(user);
        }

User.cs(在另一个项目中,但在相同的解决方案中)

namespace FaceToFace.Model
{
    public class User
    {
        public int UserID { get; set; }
        public string CodeName { get; set; }
        public bool UseBriefInstructions { get; set; }
        public ICollection<RegimeItem> RegimeItems { get; set; }
        public Device Device { get; set; }
        public virtual ICollection<Grading> UserGradings { get; set; }
        public User()
        {
            this.RegimeItems = new List<RegimeItem>();
            Device = new Device();
        }   
    }
    public class RegimeItem
    {
        public int RegimeItemID { get; set; }
        public Exercise RegimeExercise { get; set; }
    }
}

Device.cs(在另一个项目中,但在相同的解决方案中)

namespace FaceToFace.Model
{
    public class Device
    {
        public int DeviceID { get; set; }
        public string Name { get; set; }
    }
}

UserDeviceViewModel.cs

namespace FaceToFaceWebsite.Models
{
    public class UserDeviceViewModel
    {
        public Device Device { get; set; }
        public User User { get; set; }
        public IList<SelectListItem> Name { get; set; }
    }
}

查看/患者/Create.cshtml

    @model FaceToFace.Model.User

    @{
        ViewBag.Title = "Create";
    }

    <h2>Create</h2>

    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)

        <fieldset>
            <legend>User</legend>

            <div class="editor-label">
                @Html.LabelFor(model => model.CodeName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.CodeName)
                @Html.ValidationMessageFor(model => model.CodeName)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.Device.Name, "Device")
            </div>
            <div class="editor-field">
            @Html.DropDownListFor(model => model.Device.DeviceID, (IEnumerable<SelectListItem>)ViewBag.DeviceID)

            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.UseBriefInstructions)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.UseBriefInstructions)
                @Html.ValidationMessageFor(model => model.UseBriefInstructions)
            </div>

            <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

我相信问题出在控制器中,我一直在做,经过多次尝试,我无法从数据库中获得创建功能来将用户分配给设备的功能,因此,我们将不胜感激。

更新

PatientController.cs

private void PopulateDeviceChoices(UserDeviceViewModel model)
{
    model.DeviceChoices = db.Devices.Select(m => new SelectListItem
    {
        Text = m.Name,
        Value = m.DeviceID
    });
}
        //
        // GET: /Patient/
        public ActionResult Index()
        {
            //var viewModel = new List<FaceToFaceWebsite.Models.UserDeviceViewModel>();
            var viewModel = db.Users
                .Select(u => new UserDeviceViewModel()
            {
                User = u,
                Device = u.Device

            }).ToList();


            return View(viewModel);
        }



        public ActionResult Create(UserDeviceViewModel model, User user)
        {
            ViewBag.DeviceID = new SelectList(db.Devices, "DeviceID", "Name");


            var device = db.Devices.Find(model.DeviceId);
            user.Device = device;

            PopulateDeviceChoices(model);
            return View(model);
        }

        //
        // POST: /Patient/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(User user, Device device, UserDeviceViewModel model)
        {
            if (ModelState.IsValid)
            {

                db.Users.Add(user);
                db.Devices.Attach(device);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            PopulateDeviceChoices(model);
            return View(model);
        }

我已经按照克里斯的建议进行了更改,但是我认为我没有正确翻译它们,因为在Value = m.DeviceID时出现错误,告诉我Cannot implicitly convert type 'int' to 'string'

我已经开始工作了,但是我在视图上得到了两组用户输入行,这也不允许我仍然将设备分配给用户。 下面的创建视图的图像

更新2(Stephens建议)

PatientController.cs

public ActionResult Create()
        {
            UserDeviceCreateViewModel model = new UserDeviceCreateViewModel();
            ConfigureViewModel(model);
            return View(model);
        }

        public ActionResult Create(UserDeviceCreateViewModel model, User user, Device device)
        {
            if (!ModelState.IsValid)
            {
                ConfigureViewModel(model);
                return View(model);  
            }
            db.Users.Add(user);
            db.SaveChanges();
            return RedirectToAction("Index");

        }

从视图模型中删除Device属性。 您不是在此处添加/编辑设备,而只是将其与用户关联。

然后,您需要将IEnumerable<SelectListItem>添加到包含可能的设备选项的视图模型:

public IEnumerable<SelectListItem> DeviceChoices { get; set; }

您将在GET和POST操作中初始化此列表,因此您可能应该将初始化逻辑分解为控制器中自己的私有方法:

private void PopulateDeviceChoices(UserDeviceViewModel model)
{
    model.DeviceChoices = db.Devices.Select(m => new SelectListItem
    {
        Text = m.Name,
        Value = m.Id
    };
}

然后,在操作中,请在返回视图之前调用此方法:

PopulateDeviceChoices(model);
return View(model);

您没有为Device on User定义显式外键属性,这有一点点困扰。 不必 ,但它使事情变得更加简单。 如果要添加显式属性,则可以执行以下操作:

@Html.DropDownListFor(m => m.User.DeviceId, Model.DeviceChoices)

但是,由于您没有此显式属性,因此您必须采取一些额外的步骤。 首先,您需要在视图模型中添加属性以保存发布的ID:

public int DeviceId { get; set; }

然后,在您的视图中,将通过以下方式呈现下拉列表:

@Html.DropDownListFor(m => m.DeviceId, Model.DeviceChoices)

最后,在操作中,您必须使用此ID从数据库中查找设备,然后在用户上进行设置:

var device = db.Devices.Find(model.DeviceId);
user.Device = device;

您收到的错误是因为DeviceID属性为typeof intValue属性为typeof string因此需要

model.DeviceChoices = db.Devices.Select(m => new SelectListItem
{
    Text = m.Name,
    Value = m.DeviceID.ToString()
});

但是,您的代码还有很多其他问题,例如您的Create() GET方法不仅具有不必要的参数,而且其属性将为null,视图基于User但是POST方法也具有DeviceUserDeviceViewModel参数,两者都将为null,并且如果您向任何模型添加验证属性,则ModelState可能无效。 与往常一样,您应该使用视图模型来表示要显示/编辑的内容

public class UserCreateVM
{
  [Display(Name = "Code Name")]
  [Required(ErrorMessage = "Please enter a code name")]
  public string CodeName { get; set; }
  [Display(Name = Use Brief Instructions?")]
  public bool UseBriefInstructions { get; set; }
  [Display(Name = Device")]
  [Required(ErrorMessage = "Please select a device")]
  public int? SelectedDevice { get; set; }
  public SelectList DeviceList { get; set; }
}

控制者

public ActionResult Create()
{
  UserCreateVM model = new UserCreateVM();
  ConfigureViewModel(model);
  return View(model);
}

[HttpPost]
public ActionResult Create(UserCreateVM model)
{
  if (!ModelState.IsValid)
  {
    ConfigureViewModel(model);
    return View(model);
  }
  // Initialize new instance of the data model
  User user = new User();
  // Map properties from view model to data model
  user.CodeName = model.CodeName;
  user.UseBriefInstructions = model.UseBriefInstructions;
  user.Device = db.Devices.Find(model.SelectedDevice);
  // Save and redirect
  db.Users.Add(user);
  db.SaveChanges();
  return RedirectToAction("Index");
}

private void ConfigureViewModel(UserCreateVM model)
{
  model.DeviceList = new SelectList(db.Devices, "DeviceID", "Name");
}

视图

@model UserCreateVM
@using (Html.BeginForm())
{
  ....
  @Html.LabelFor(m => m.CodeName)
  @Html.TextBoxFor(m => m.CodeName)
  @Html.ValidationMessageFor(m => m.CodeName)

  @Html.LabelFor(m => m.SelectedDevice)
  @Html.DropDownListFor(m => m.SelectedDevice, Model.DeviceList, "-Please select-")
  @Html.ValidationMessageFor(m => m.SelectedDevice)

  @Html.LabelFor(m => m.UseBriefInstructions)
  @Html.CheckboxFor(m => m.UseBriefInstructions)
  @Html.ValidationMessageFor(m => m.UseBriefInstructions)
  ....
}

暂无
暂无

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

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