我正在创建一个系统,在创建用户时,可以将设备分配给该用户。我通过下拉列表执行此操作,虽然下拉列表中填充了设备列表,但它不会使用该设备更新用户。多个用户可以使用相同的设备,我想避免硬编码,因为信息已经存在于数据库中。
我通过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'
我已经开始工作了,但是我在视图上获得了两组用户输入行,它也不允许我将设备分配给用户。
更新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");
}
答案 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方法还包含Device
和UserDeviceViewModel
的参数,两者都是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)
....
}