[HttpPost] Edit ActionメソッドCustomerDeviceControllerのCheckBoxListの値をデータベースのCustomerDeviceテーブルに更新する方法を理解できません。ASP.NET Core MVCデータベースのCheckBoxListの値を編集します。
My Index Action Method for CustomerDeviceControllerは、CustomersテーブルからCustomersのリストを表示します。私はCustId値をCustomerDeviceController [HttpGet] Edit(int?id)Action Methodに渡すActionLinkというラベルの "Edit"を持っています.CastIdに割り当てられたすべての選択されたDevId値をCheckBoxListに表示します。
CheckBoxListの値を更新しようとすると、以下のエラーメッセージが表示されます。私はそれらを更新する前に、私がループして、DevIdの値を削除する必要があると言われました。これは私が理解できない部分です。 CheckBoxListの
「System.InvalidOperationException」種類の例外更新
エラーメッセージはMicrosoft.EntityFrameworkCore.dllで発生したが、ユーザーコードで処理されなかった
追加情報:エンティティタイプのインスタンス同じキーを持つこのタイプの別のインスタンスがすでに追跡されているため、 'CustomerDevice'を追跡できません。新しいエンティティを追加する場合、ほとんどのキータイプで、キーが設定されていない場合(キープロパティにそのタイプのデフォルト値が割り当てられている場合)、一意の一時キー値が作成されます。新しいエンティティのキー値を明示的に設定する場合は、既存のエンティティや他の新しいエンティティ用に生成された一時的な値と衝突しないようにしてください。既存のエンティティをアタッチする場合は、指定されたキー値を持つエンティティインスタンスが1つだけコンテキストにアタッチされていることを確認します。
モデル
public class CheckBoxListItem
{
public int ID { get; set; }
public string Display { get; set; }
public bool IsChecked { get; set; }
}
public class Customer
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
...
}
public class Device
{
public int DevId { get; set; }
public string DevType { get; set; }
}
public class CustomerDevice
{
public int CustId { get; set; }
public int DevId { get; set; }
public Customer Customer { get; set; }
public Device Device { get; set; }
}
のviewmodels
public class CustomerDeviceFormViewModel
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public List<CheckBoxListItem> Devices { get; set; }
}
CustomerDeviceController
public ActionResult Create(int? id)
{
if (id == null)
{
return NotFound();
}
var customervm = new CustomerDeviceFormViewModel();
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
if (customer == null)
{
return NotFound();
}
customervm.CustId = customer.CustId;
customervm.CustDisplayName = customer.CustDisplayName;
// Retrieves list of Devices for CheckBoxList
var deviceList = db.Devices.ToList();
var checkBoxListItems = new List<CheckBoxListItem>();
foreach (var device in deviceList)
{
checkBoxListItems.Add(new CheckBoxListItem()
{
ID = device.DevId,
Display = device.DevType,
IsChecked = false //On the create view, no devices are selected by default
});
}
customervm.Devices = checkBoxListItems;
return View(customervm);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerDeviceFormViewModel vm)
{
if (ModelState.IsValid)
{
foreach (var deviceId in vm.Devices.Where(x => x.IsChecked).Select(x => x.ID))
{
var customerDevices = new CustomerDevice
{
CustId = vm.CustId,
DevId = deviceId
};
db.CustomerDevices.Add(customerDevices);
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
public ActionResult Edit(int? id)
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
if (customer == null)
{
return NotFound();
}
// Get all devices
var deviceList = db.Devices.ToList();
// Get the selected device ID's for the customer
IEnumerable<int> selectedDevices = db.CustomerDevices
.Where(x => x.CustId == id).Select(x => x.DevId);
// Build view model
var model = new CustomerDeviceFormViewModel()
{
CustId = customer.CustId,
CustDisplayName = customer.CustDisplayName,
Devices = deviceList.Select(x => new CheckBoxListItem()
{
ID = x.DevId,
Display = x.DevType,
IsChecked = selectedDevices.Contains(x.DevId)
}).ToList()
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomerDeviceFormViewModel vmEdit)
{
if (ModelState.IsValid)
{
Customer customer = db.Customers
.Include(c => c.CustomerDevices)
.SingleOrDefault(c => c.CustId == vmEdit.CustId);
if (customer == null)
{
return NotFound();
}
IEnumerable<int> selectedDevices = vmEdit.Devices.Where(x => x.IsChecked).Select(x => x.ID);
// Remove all selected devices for this customer
foreach (int removeId in selectedDevices)
{
customer.CustomerDevices.Clear();
}
// Add the new selected devices
foreach (int deviceId in selectedDevices)
{
CustomerDevice customerDevice = new CustomerDevice
{
CustId = customer.CustId,
DevId = deviceId
};
customer.CustomerDevices.Add(customerDevice);
}
// Update the customer
db.Customers.Update(customer); //or just db.Update(customer); same thing
// // Save and redirect
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vmEdit);
}
編集ビュー
<div class="form-group">
Please select the Devices to assign to <b>@Html.DisplayFor(c => c.CustDisplayName)</b>
</div>
<div class="form-group">
@Html.EditorFor(x => x.Devices)
</div>
@Html.HiddenFor(c => c.CustId)
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
共有/ EditorTemplates/CheckBoxListItem.chtml
<div class="checkbox">
<label>
@Html.HiddenFor(x => x.ID)
@Html.CheckBoxFor(x => x.IsChecked)
@Html.LabelFor(x => x.IsChecked, Model.Display)
</label>
<br />
WebFormContext
public class WebFormContext : DbContext
{
public WebFormContext(DbContextOptions<WebFormContext> options)
: base(options)
{ }
public DbSet<Customer> Customers { get; set; }
public DbSet<State> States { get; set; }
public DbSet<Device> Devices { get; set; }
public DbSet<CustomerDevice> CustomerDevices { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>()
.HasKey(c => c.CustId);
modelBuilder.Entity<Customer>()
.Property(c => c.CustDisplayName)
.HasColumnType("varchar(100)")
.HasMaxLength(100)
.IsRequired();
modelBuilder.Entity<Customer>()
.Property(c => c.CustFirstName)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
modelBuilder.Entity<Customer>()
.Property(c => c.CustLastName)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
modelBuilder.Entity<Customer>()
.Property(c => c.CustCompanyName)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
modelBuilder.Entity<Customer>()
.Property(c => c.CustAddress)
.HasColumnType("varchar(100)")
.HasMaxLength(100)
.IsRequired();
modelBuilder.Entity<Customer>()
.Property(c => c.CustPhoneNumber)
.HasColumnType("varchar(12)")
.HasMaxLength(12);
modelBuilder.Entity<Customer>()
.Property(c => c.CustMobileNumber)
.HasColumnType("varchar(12)")
.HasMaxLength(12);
modelBuilder.Entity<Customer>()
.Property(c => c.CustEmailAddress)
.HasColumnType("varchar(320)")
.HasMaxLength(320);
modelBuilder.Entity<Device>()
.HasKey(d => d.DevId);
modelBuilder.Entity<Device>()
.Property(d => d.DevType)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<CustomerDevice>()
.HasKey(cd => new { cd.CustId, cd.DevId });
}
}