I'm trying to get the result of my enum for a location as a string but for some reason, it's only showing it as an integer in the index page.
Model
public class UserLicense
{
[Key]
public string Location { get; set; }
}
Enum Class
public enum LocationType
{
Brazil,
USA,
UK
//etc .. here i will add around another 30 items
}
Controller
public async Task<IActionResult> Create(IFormCollection col)
{
if (!User.Identity.IsAuthenticated) RedirectToAction("Index", "Home");
UserLicense uc = new UserLicense();
if (ModelState.IsValid)
{
try
{
DateTime? ends = null;
if (DateTime.TryParse(col["ends"], out DateTime tmp)) ends = tmp;
string username = col["user.username"].ToString().Normalize();
var user = _context.Users.FirstOrDefault(x => x.NormalizedUsername == username);
uc = new UserLicense
{
Ends = ends,
Starts = DateTime.Parse(col["starts"]),
UserId = user.Id,
LicenseId = int.Parse(col["licenseid"]),
Location = Enum.GetName(typeof(LocationType),col["Location"]), //the issue is here.
};
_context.Add(uc);
await _context.SaveChangesAsync();
Create HTML
<div class="form-group">
<label asp-for="Location" class="control-label"></label>
<select asp-for="Location" class="form-control" asp-items="#Html.GetEnumSelectList<LocationType>()"></select>
<span asp-validation-for="Location" class="text-danger"></span>
</div>
Since you are using IFormCollection to transfer the parameters to the controller, not matter using public string Location { get; set; } or public string Location { get; set; }, in the controller the Location value in the IFormCollection will be always an integer. So, you could based on the int value to get string value from the Enum:
var location = ((LocationType)int.Parse(col["location"])).ToString();
The result like this:
Besides, there has another solution, you could use the Strongly typed data (use UserLicense model in the action method, instead of IFormCollection) to transfer the parameter to the controller.
Code like this:
public class UserLicense
{
[Key]
public int License { get; set; }
public DateTime Ends { get; set; }
public DateTime Starts { get; set; }
public int UserId { get; set; }
public LocationType Location { get; set; }
}
public enum LocationType
{
Brazil,
USA,
UK
}
and
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create(UserLicense userLicense)
{
if (ModelState.IsValid)
{
var location = userLicense.Location;
return RedirectToAction(nameof(Index));
}
return View();
}
Code in the Create.cshtml:
#model WebApplication1.Models.UserLicense
#{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Create</h1>
<h4>UserLicense</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="License" class="control-label"></label>
<input asp-for="License" class="form-control" />
<span asp-validation-for="License" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Ends" class="control-label"></label>
<input asp-for="Ends" class="form-control" />
<span asp-validation-for="Ends" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Starts" class="control-label"></label>
<input asp-for="Starts" class="form-control" />
<span asp-validation-for="Starts" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="UserId" class="control-label"></label>
<input asp-for="UserId" class="form-control" />
<span asp-validation-for="UserId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Location" class="control-label"></label>
<select asp-for="Location" class="form-control" asp-items="#Html.GetEnumSelectList<LocationType>()"></select>
<span asp-validation-for="Location" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
The screenshot as below:
Make your Location property a type of LocationType instead of string.
public class UserLicense
{
[Key]
public LocationType Location { get; set; }
}
Pass Location to the view from the Create action like this
uc = new UserLicense
{
Ends = ends,
Starts = DateTime.Parse(col["starts"]),
UserId = user.Id,
LicenseId = int.Parse(col["licenseid"]),
Location = uc.Location
};
Then in the view
<select asp-for="Location" class="form-control" asp-items="#Html.GetEnumSelectList<LocationType>()">
<option selected="selected" value="">Please Select</option>
</select>
Related
I am building a to-do-list project as a practice. It has one relationship to the Member model and the Member model has many relationships to 'to-do-list'
Member controller create method works without any issue but the to-do-list controller throws model state is invalid on Member object property of to-do-list
ToDoList
using System.ComponentModel.DataAnnotations;
namespace To_Do_List.Models
{
public class ToDoList
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(200, MinimumLength = 1, ErrorMessage = "To Do List Item cannot be longer than 200 characters.")]
public string Title { get; set; }
public string Description { get; set; }
[DataType(DataType.Date)]
public DateTime DueDate { get; set; }
public string Priority { get; set; }
public int AssignToId { get; set; }
public Member AssignTo { get; set; }
[Required]
[StringLength(15, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.")]
[RegularExpression("^(Completed|Not Completed)$", ErrorMessage = "The status must be Completed or Not Completed")]
public string Status { get; set; }
}
}
Member
using Microsoft.Build.Framework;
namespace To_Do_List.Models
{
public class Member
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
[Required]
public ICollection<ToDoList> ToDoLists { get; set; }
}
}
create method of to do list controller
public async Task<IActionResult> Create([Bind("Id,Title,Description,DueDate,Priority,AssignToId,AssignTo, Status")] ToDoList toDoList)
{
if (ModelState.IsValid)
{
_context.Add(toDoList);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["AssignToId"] = new SelectList(_context.Members, "Id", "Id", toDoList.AssignToId);
return View(toDoList);
}
View method of to do list
public IActionResult Create()
{
return View();
}
Create.cshtml
#model To_Do_List.Models.ToDoList
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>ToDoList</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DueDate" class="control-label"></label>
<input asp-for="DueDate" class="form-control" />
<span asp-validation-for="DueDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Priority" class="control-label"></label>
<input asp-for="Priority" class="form-control" />
<span asp-validation-for="Priority" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Status" class="control-label"></label>
<input asp-for="Status" class="form-control" />
<span asp-validation-for="Status" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Member controller create method works without any issue but the
to-do-list controller throws model state is invalid on Member object
property of to-do-list
Well, I have succssfully reproducced your issue and your ModelState.IsValid false is logical. Because, when you leave public Member AssignTo { get; set; } with default annotation it means required. whilist, you haven't pass any property from your view consequently, your bindings always be false as you have defined it into the [Bind] property that is AssignTo However, value has not been pass to it.
How to resolve:
In this scenario, you either has to pass AssignTo to your create action or make it nullable using ? annotation as following:
public Member? AssignTo { get; set; }
Note: If you don't want to set AssignTo as nullable then you have to pass all property value from your view as following:
<div class="form-group">
<label asp-for="AssignTo.Name" class="control-label"></label>
<input asp-for="AssignTo.Name" class="form-control" />
<span asp-validation-for="AssignTo.Name" class="text-danger"></span>
</div>
Here, I am passing only AssignTo.Name you have to pass rest of the values.
Output:
Note: If you would like to know more details on it you could check our official document here.
I have a form that adds a branch, the form has a drop down to select the company name.
I created a viewModel that has the SelectListItem of the companies and the Branch Model
When submit a form, modelState.IsValid equals to false.
reason for that is because CompaniesList is required.
any idea why is it required? how can i overcome this?
Branch model:
public class Branch
{
public int Id { get; set; }
public int CompanyId { get; set; }
[MaxLength(50)]
public string? City { get; set; }
[MaxLength(50)]
public string? BranchName { get; set; }
public DateTime CreatedAt { get; set; }
[MaxLength(100)]
public string? CreatedBy { get; set; }
}
ViewModel:
public class BranchVM
{
public Branch branch { get; set; }
[AllowNull]
public IEnumerable<SelectListItem> CompaniesList { get; set; }
}
Create.cshtml:
#model Click2Lock.Models.BranchVM
<form method="post" enctype="multipart/form-data">
<div class="border p-3 mt-4">
<div class="row pb-2">
<h2 class="text-primary">Create Branch</h2>
<hr/>
</div>
<div class="col-8">
<label asp-for="branch.BranchName">Branch Name</label>
<input asp-for="branch.BranchName" class="form-control"/>
<span asp-validation-for="branch.BranchName" class="text-danger"></span>
</div>
<div class="col-8">
<label asp-for="branch.City">City</label>
<input asp-for="branch.City" class="form-control"/>
<span asp-validation-for="branch.City" class="text-danger"></span>
</div>
<div class="col-8 pb-4">
<div class="form-group row">
<div class="col-4">
<label asp-for="branch.CompanyId">Company</label>
</div>
<div class="col-8">
#Html.DropDownListFor(m => m.branch.CompanyId, Model.CompaniesList , "Select Order",
new { #class = "form-control" })
<span asp-validation-for="branch.CompanyId" class="text-danger"></span>
</div>
</div>
</div>
<div class="col-8">
<input type="hidden" asp-for="branch.CreatedAt" class="form-control" value="#DateTime.Now" />
</div>
<div class="col-8">
<input type="hidden" asp-for="branch.CreatedBy" class="form-control" value=#ViewBag.userName />
</div>
<button type="submit" class="btn btn-primary" style="width:200px">Add New Branch</button>
<a asp-controller="Company" asp-action="Index" class="btn btn-secondary" style="width:150px">
Back To List
</a>
</div>
</form>
create on Controller :
public IActionResult Create()
{
ViewBag.userName = (_unitOfWork.ApplicationUser.GetAll().
Where(q => q.UserName == User.Identity.Name).Select(q => q.FullName)).FirstOrDefault();
BranchVM branchVM = new BranchVM()
{
branch = new Branch(),
CompaniesList = _unitOfWork.Company.GetAll().OrderBy(a=>a.CompanyName).
Select(i => new SelectListItem
{
Text = i.CompanyName,
Value = i.Id.ToString()
})
};
return View(branchVM);
}
//POST
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(BranchVM branchVM)
{
ViewBag.msgCreate = 0;
ViewBag.msgGeneralException = 0;
if (ModelState.IsValid)
{
try
{
_unitOfWork.Branch.Add(branchVM.branch);
_unitOfWork.Save();
ViewBag.msgCreate = 1;
return View(branchVM);
}
catch (Exception ex)
{
ViewBag.msgGeneralException = 1;
return View(branchVM);
}
}
ViewBag.msgGeneralException = 1;
return View(branchVM);
}
One technique is to make it nullable:
public IEnumerable<SelectListItem>? CompaniesList { get; set; }
This is my Index Action,
I give all products to my view
public async Task<IActionResult> Index()
{
return View(await _productRepo.GetAllAsync());
}
This is my Create Action,
I selected all categories Id and Name to View.Categories
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,SKU,Description,Price,OldPrice,Status,IsMenuItem,Count,CategoryId")] Product productModel)
{
ViewBag.Categories = new SelectList(await _categoryrepo.GetAllAsync() , "Id" , "Name");
if (ModelState.IsValid)
{
await _productRepo.CreateAsync(productModel);
return RedirectToAction(nameof(Index));
}
return View(productModel);
}
This is my view
#model OnlineShopArmenia.Models.Product
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Product</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SKU" class="control-label"></label>
<input asp-for="SKU" class="form-control" />
<span asp-validation-for="SKU" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Status" /> #Html.DisplayNameFor(model => model.Status)
</label>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="IsMenuItem" /> #Html.DisplayNameFor(model => model.IsMenuItem)
</label>
</div>
<div class="form-group">
<label asp-for="Count" class="control-label"></label>
<input asp-for="Count" class="form-control" />
<span asp-validation-for="Count" class="text-danger"></span>
</div>
<div class="form-group">
<label>Categories :</label>
<select name="Id" asp-for="Id" class="formcontrol" asp-items="ViewBag.Categories">
<option value="#ViewBag.Categories"></option>
</select>
<span asp-validation-for="Id" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
This is Product Model
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string SKU { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public bool Status { get; set; }
public bool IsMenuItem { get; set; }
public int Count { get; set; }
public int? CategoryId { get; set; }
public Category Category { get; set; }
}
This is Category Model
public class Category
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
This is the result
I want to see Categories in dropdown list, how can I do it ?
I think that we must change attributes in <select> and <option> tags,
Please, help me to fix it
You are using the wrong action method. For create operation your controller should have two action methods - a GET method and a POST method. The one you are using now (marked with [HttpPost]) is for receiving data from your view, once you try to save them. To pass data to the view (while you are creating it), use an action method marked with [HttpGet] attribute (or, not marked with any attribute at all). Following GET method should be sufficient to create your view -
[HttpGet] // this attribute is optional
public IActionResult Create()
{
ViewBag.Categories = new SelectList(await _categoryrepo.GetAllAsync() , "Id" , "Name");
return View();
}
You are marking the select tag wrong, it should represent the foreign key property CategoryId, not the Id of the product -
<select asp-for="CategoryId" class ="form-control" asp-items="ViewBag.Categories"></select>
You don't need the option tag unless you want a display-value like Please select a Category or something -
<select asp-for="CategoryId" class ="form-control" asp-items="ViewBag.Categories">
<option value="">Please choose user category:</option>
</select>
EDIT :
I'm not sure what version of ASP.NET MVC or, ASP.NET Core MVC you are using, but the razor syntax above works in .NET 5.
you should have 2 actions -to create or edit view and save data.
Your action to create view should be looking like this:
[HttpGet] // this attribute is optional
public async Task<IActionResult> Create()
{
return await Edit(0);
}
[HttpGet("{id?}")]
public async Task<IActionResult> Edit(int id)
{
ProductModel model=null;
if id=0 model=new Product();
else model= await _productRepo.GetAsync(id);
ViewBag.Categories = new SelectList(await _categoryrepo.GetAllAsync()
, "Id" , "Name");
return View(model);
}
and fix your select:
<select name="categoryId" asp-for="CategoryId" class="formcontrol" asp-items="#ViewBag.Categories">
</select>
I am attempting to add a feature which allows users to upload a photo of their pets. I am new to MVC and am using this tutorial as guidance: https://www.codaffection.com/asp-net-core-article/asp-net-core-mvc-image-upload-and-retrieve/
View:
#model PetPhotoModel;
#{
ViewData["Title"] = "Upload A photo of your pet";
}
<div class="row">
<div class="col-md-4">
<form asp-action="UploadPhoto">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="PetName" class="control-label"></label>
<input asp-for="PetName" class="form-control" />
<span asp-validation-for="PetName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ImageFile" class="control-label"></label>
<input asp-for="ImageFile" accept="image/*" />
<span asp-validation-for="ImageFile" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="UploadPhoto" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Controller (partial):
...
public IActionResult UploadPhoto()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadPhoto([Bind("Id,PetName,Title,Description,ImageFile")] PetPhotoModel petPhotoModel)
{
if (ModelState.IsValid)
{
//Save image to wwwroot/image
string wwwRootPath = _hostEnvironment.WebRootPath;
string fileName = Path.GetFileNameWithoutExtension(petPhotoModel.ImageFile.FileName);
string extension = Path.GetExtension(petPhotoModel.ImageFile.FileName);
petPhotoModel.ImageName = fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
string path = Path.Combine(wwwRootPath + "/Image/", fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await petPhotoModel.ImageFile.CopyToAsync(fileStream);
}
//GetLoggedInUser() gets the current user by id from the db context
GetLoggedInUser().Uploads.Add(petPhotoModel);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(petPhotoModel);
}
...
The UserModel contains a collection of PetPhotoModel in order to create a 1 to many relationship in the database:
public virtual ICollection<PetPhotoModel> Uploads { get; set; }
PetPhotoModel:
public class PetPhotoModel
{
private DateTime _dateUploaded = DateTime.Now;
public int Id { get; set; }
[Required]
public string PetName { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
[Column(TypeName = "nvarchar(100)")]
[DisplayName("Image Name")]
public string ImageName { get; set; }
[NotMapped]
[DisplayName("Upload File")]
public IFormFile ImageFile { get; set; }
public DateTime DateUploaded
{
get { return _dateUploaded; }
set { _dateUploaded = value; }
}
...
The issue is after the submit button is pressed that the controller does not get any data about image from the view at all despite the image being uploaded in the view:
[
When the form includes any type file elements you have to use "multipart/form-data" encoding. Since default encoding is "application/x-www-form-urlencoded", change form tag in your view to this:
<form asp-action="UploadPhoto" enctype="multipart/form-data" method="post">
I'm trying to update a table(FlightClasses) with multiple rows having relation of one to many with table(Flight) but i can't update it with the changed values
Can anyone help me with that
Model class of Flight
i want to update rows on other table of flightclasses linked with row in this table
namespace Airline.Models
{
public class FlightModel
{
public int Id { get; set; }
public string FlightName { get; set; }
public string FlightNo { get; set; }
public string OriginCity { get; set; }
public string DestinationCity { get; set; }
public DateTime Departure { get; set; }
public DateTime Arrival { get; set; }
public virtual ICollection<FlightClassesModel> FlightClasses { get; set; }
}
}
Model class of FlightClasses
namespace Airline.Models
{
public class FlightClassesModel
{
public int FlightClassesModelId { get; set; }
public type Class { get; set; }
public int AvailableSeats { get; set; }
public double Price { get; set; }
public virtual FlightModel Flight { get; set; }
public int? FlightId { get; set; }
}
public enum type
{
Business_Class,
First_Class,
Club_Class
}
}
View
#model Airline.Models.FlightModel
#{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>FlightModel</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="FlightName" class="control-label"></label>
<input asp-for="FlightName" class="form-control" />
<span asp-validation-for="FlightName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="FlightNo" class="control-label"></label>
<input asp-for="FlightNo" class="form-control" />
<span asp-validation-for="FlightNo" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="OriginCity" class="control-label"></label>
<input asp-for="OriginCity" class="form-control" />
<span asp-validation-for="OriginCity" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DestinationCity" class="control-label"></label>
<input asp-for="DestinationCity" class="form-control" />
<span asp-validation-for="DestinationCity" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Departure" class="control-label"></label>
<input asp-for="Departure" class="form-control" />
<span asp-validation-for="Departure" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Arrival" class="control-label"></label>
<input asp-for="Arrival" class="form-control" />
<span asp-validation-for="Arrival" class="text-danger"></span>
</div>
#foreach (var flightClass in Model.FlightClasses)
{
<div class="form-group">
<label asp-for="#flightClass.Class" class="control-label"></label>
<select class="form-control" asp-for="#flightClass.Class" asp-items="Html.GetEnumSelectList<type>()"></select>
<span asp-validation-for="#flightClass.Class" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#flightClass.AvailableSeats" class="control-label"></label>
<input asp-for="#flightClass.AvailableSeats" class="form-control" />
<span asp-validation-for="#flightClass.AvailableSeats" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#flightClass.Price" class="control-label"></label>
<input asp-for="#flightClass.Price" class="form-control" />
<span asp-validation-for="#flightClass.Price" class="text-danger"></span>
</div>
}
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
controller
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var flightModel = await _context.Flight.FindAsync(id);
if (flightModel == null)
{
return NotFound();
}
return View(flightModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, FlightModel flightModel)
{
if (id != flightModel.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(flightModel);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!FlightModelExists(flightModel.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(flightModel);
}
This code _context.Update(flightModel); will update flightModel only, so if you wanna update FlightClasses also you must get FlightClasses from the flightModel then use _context.Update(flightClasse); for all the instances in FlightClasses. And at the end you use await _context.SaveChangesAsync();
Updating data in the Parent-Child(one to many relation) table using EntityFramework Core
we first retrieve the FlightModel entity from the database using FirstOrDefaultAsync
var entity = await _context.FlightModel
.Include(s => s.FlightClassesModel)
.FirstOrDefaultAsync(s => s.FlightModelId == id);
use SetValues on the CurrentValues of the Entry method to update the properties of the FlightModel
_context.Entry(entity).CurrentValues.SetValues(FlightModel);
Loop through the FlightClassesModel collection to update or add new child entities as needed.
foreach (var child in FlightModel.FlightClassesModel)
{
var childEntity = entity.FlightClassesModel.FirstOrDefault(c => c.FlightClassesModelId == child.FlightClassesModelId);
if (childEntity != null)
{
_context.Entry(childEntity).CurrentValues.SetValues(child);
}
else
{
entity.FlightClassesModel.Add(child);
}
}
SaveChangesAsync to persist the changes to the database.
await _context.SaveChangesAsync();