如何将现有模型(设备)数据附加到mvc asp.net中的另一个模型(用户)数据

时间:2015-03-23 12:40:12

标签: c# asp.net asp.net-mvc entity-framework asp.net-mvc-4

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

我通过ef代码首先执行此操作,其他任何建议都将被考虑在内。我真的只专注于让这个工作,所以我愿意接受建议。我也想让这个与编辑一起工作,但我假设解决方案将修复创建和编辑,如果我使用类似的代码。

我一直在使用viewmodel来显示索引页面上的设备。数据库上的当前用户显示他们分配的设备,所以我知道它可以工作,但我不得不手动分配表数据中的设备。

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>

我认为问题在于我在Controller中所做的事情,并且经过多次尝试后我无法使用create函数将用户从数据库分配给设备,因此我们将非常感谢任何帮助。

更新

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);
        }

我已经做出了克里斯&#39;建议,但我不认为我已正确翻译它们,因为我在Value = m.DeviceID收到错误,告诉我Cannot implicitly convert type 'int' to 'string'

我已经开始工作了,但是我在视图上获得了两组用户输入行,它也不允许我将设备分配给用户。 image of create view below

更新2(斯蒂芬斯建议)

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");

        }

2 个答案:

答案 0 :(得分:2)

从视图模型中删除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上为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;

答案 1 :(得分:1)

您收到的错误是因为属性DeviceID的类型为int,但Value属性的类型为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)
  ....
}