Can’t update ICollection property - c#

The problem is when I try to update Master and Details Tables at the same time.
When call Post Edit Task the Details objects don´t appear.
The Edit View displays all Details rows correctly, but while debugging the Edit POST, Casas is empty
MODELS
public partial class Modelo : IValidatableObject {
public Modelo()
{
Casas = new HashSet<Casa>();
}
public int Modeloid { get; set; }
public string Modelo1 { get; set; }
public virtual ICollection<Casa> Casas { get; set; }//Don’t work to update
}
public partial class Casa // DETAIL TABLE
{
public int Casaid { get; set; }
public int Modeloid { get; set; } // FK to Modelo
public string Casa1 { get; set; }
public virtual Modelo Modelo { get; set; }
}
CONTROLLER
public class ModelosController : Controller
. . . . . . . . .
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, Modelo modelo)
{
if (id != modelo.Modeloid)
{
return NotFound();
}
if (ModelState.IsValid)
{
// Here modelo.Modelo1 has current modified value
// but modelo.Casas.Count == 0
_context.Update(modelo);
await _context.SaveChangesAsync();
}
}
// GET: Modelos/Edit
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var modelo = await _context.Modelo
.AsNoTracking()
.Include(m => m.Fotomodelos)
.Include(m => m.Casas)
.SingleOrDefaultAsync(m => m.Modeloid == id);
if (modelo == null)
{
return NotFound();
}
return View(modelo);
}
View EDIT.CSHTML
#using System.IO
#model Disponibilidad.Models.Modelo
<form asp-action="Edit">
<div class="form-horizontal">
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Modeloid" />
<div class="form-group">
<label asp-for="Modelo1" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Modelo1" class="form-control" />
<span asp-validation-for="Modelo1" class="text-danger"></span>
</div>
</div>
#{
for (int i = 0; i < Model.Casas.Count; i++)
{
<input type="hidden" asp-for="#Model.Casas.ElementAt(i).Modeloid"
value="#Model.Modeloid" />
<input type="hidden" asp-for="#Model.Casas.ElementAt(i).Casaid" />
<div class="form-group">
<label asp-for="#Model.Casas.ElementAt(i).Casa1"
class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="#Model.Casas.ElementAt(i).Casa1"
class="form-control" /> <!-- DISPLAY OK Detail rows -->
<span asp-validation-for="#Model.Casas.ElementAt(i).Casa1"
class="text-danger"></span>
</div>
</div>
}
}
<div class="btn-group">
<button type="submit" class="btn btn-danger">Save</button>
</div>
</div>
</form>

When you use a for cycle instead of foreach in Razor, the name of the properties doesn't get rendered correctly when using the default asp-for TagHelpers.
You can correct your example changing your razor form inputs as follow:
From:
<input type="hidden" asp-for="#Model.Casas.ElementAt(i).Casaid" />
To:
<input type="hidden" name="modelo.Casas[#i].Casaid" value="#Model.Casas.ElementAt(i).Casaid" />

Related

How to upload an image from ASP.net MVC to VARBINARY in a database

I've been trying for a while to try to get my project to accept image files and submit them to my database, but to no avail. Everything I see is 10+ years old and no longer works.
It's just the basic Edit view for MVC, I just beefed up security.
public async Task<IActionResult> Edit([Bind("UserId,Name,Email,Password,Type,EmailConfirm,Pfp")] UserIdentity userIdentity)
{
//check if user is logged in for this action
if (HttpContext.Session.GetInt32("sessionUserID") == null || HttpContext.Session.GetInt32("sessionUserID") <= 0)
{
ViewBag.reasonFailed = "You need to log in before doing this!";
return View("Failed");
}
//for use in LINQ queries
MySchoolDataContext dbContext = new();
//checks if the user is an admin
if ((from user in dbContext.UserIdentities where user.UserId == userIdentity.UserId select user.Type).FirstOrDefault().Equals("A"))
{
}
else
{
//Checking if the userID matches the id in the URL
if (HttpContext.Session.GetInt32("sessionUserID") != userIdentity.UserId)
{
ViewBag.reasonFailed = "You cannot edit an account that isn't your own!";
return View("Failed");
}
//checks if the email is confirmed
if ((from user in dbContext.UserIdentities where user.UserId == HttpContext.Session.GetInt32("sessionUserID") select user.EmailConfirm).FirstOrDefault().Equals("n"))
{
return RedirectToAction("confirmEmail");
}
}
if (userIdentity.UserId != userIdentity.UserId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(userIdentity);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserIdentityExists(userIdentity.UserId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(userIdentity);
}
The view I'm using:
#model Rideshare.Models.UserIdentity
#{
ViewData["Title"] = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Edit</h1>
<h4>UserIdentity</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="UserId" />
<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="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Type" class="control-label"></label>
<input asp-for="Type" class="form-control" />
<span asp-validation-for="Type" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmailConfirm" class="control-label"></label>
<input asp-for="EmailConfirm" class="form-control" />
<span asp-validation-for="EmailConfirm" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Pfp" class="control-label"></label>
<input asp-for="Pfp" type="file" class="form-control" />
<span asp-validation-for="Pfp" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Thank you for any help you give. This is for a school project and not even my professor knows how to pull it off. I've asked.
Edit: Someone asked for the model that I'm using for it, so here it is.
using System;
using System.Collections.Generic;
#nullable disable
namespace Rideshare.Models
{
public partial class UserIdentity
{
public UserIdentity()
{
HistoryDrivers = new HashSet<History>();
HistoryPasses = new HashSet<History>();
RatingRaters = new HashSet<Rating>();
RatingUsers = new HashSet<Rating>();
}
public int UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string Type { get; set; }
public string EmailConfirm { get; set; }
public byte[] Pfp { get; set; }
public virtual ICollection<History> HistoryDrivers { get; set; }
public virtual ICollection<History> HistoryPasses { get; set; }
public virtual ICollection<Rating> RatingRaters { get; set; }
public virtual ICollection<Rating> RatingUsers { get; set; }
}
}
I'm completly changing this because I was slightly wrong in how I converted the image to a byte array. There is actually a very easy way to do this! It just took a lot of Googling and rabbit holes(also my teacher!). I just used a MemoryStream and IFormFile to because you can convert straight from one to the other.
public async Task<IActionResult> ChangePfp(IFormFile theFile, [Bind("UserId,Name,Email,Password,Type,EmailConfirm,Pfp")] UserIdentity userIdentity)
{
//check file length just in case of null
if (theFile.Length > 0)
{
//converting the image(file) to a byte array(MemoryStream)
using (MemoryStream mStream = new())
{
theFile.CopyTo(mStream);
userIdentity.Pfp = mStream.ToArray();
}
}
else
{
return View();
}
if (ModelState.IsValid)
{
try
{
_context.Update(userIdentity);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserIdentityExists(userIdentity.UserId))
{
ViewBag.reasonFailed = "Not found";
return View("Failed");
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(userIdentity);
}
This is the code I used to do it, but with the bulk taken out to make it easier to read and make some of it private. It really was just this easy. To convert it back in the view, all you have to do is this in the view you want it in:
#if (Model.Pfp != null)
{
<img src="data:image/jpeg;base64,#(Convert.ToBase64String(Model.Pfp))"/>
}
Thank you to everyone who tried to help!

this ViewDataDictionary instance requires a model item of type 'lms.Web.Models.ProductVM.ProductEditViewMode

I'm creating asp .net core web application using Layered Architecture but when I am working with Edit action face that error. How can I solve the error?
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the
ViewDataDictionary is of type 'lms.Model.Product', but this
ViewDataDictionary instance requires a model item of type
'lms.Web.Models.ProductVM.ProductEditViewModel'.
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(object
value)
**#ProductController**
public IActionResult Edit(int id)
{
var prod = _productService.GetById(id);
return View(prod);
}
[HttpPost]
public IActionResult Edit(ProductEditViewModel model)
{
if (ModelState.IsValid)
{
var product = _mapper.Map<Product>(model);
bool isSaved = _productService.Update(product);
if (isSaved)
{
return RedirectToAction(nameof(Index));
}
}
return View();
}
#ProductRepository
public class ProductRepository:Repository<Product>,IProductRepository
{
private readonly ApplicationDbContext _db;
public ProductRepository(ApplicationDbContext db) : base(db)
{
_db = db;
}
public override ICollection<Product> GetAll()
{
return _db.Products.Include(c => c.Category).ToList();
}
public ICollection<Product> GetByCategory(int categoryId)
{
return _db.Products.Where(c => c.CategoryId == categoryId).ToList();
}
}
#ProductService
private IProductRepository _productRepository;
public ProductService(IProductRepository repository) : base(repository)
{
_productRepository = repository;
}
//public ICollection<Product> GetByYear(int year)
//{
// throw new NotImplementedException();
//}
public ICollection<Product> GetByCategory(int categoryId)
{
var products = _productRepository.GetByCategory(categoryId);
return products;
}
#ProductEditViewModel
public class ProductEditViewModel
{
public string Name { get; set; }
public double Price { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
[Display(Name = "Category")]
public int? CategoryId { get; set; }
public List<SelectListItem> CategoryItemList { get; set; }
//public ICollection<global::lms.Model.Product> ProductList { get; set; }
}
#EditView
#model lms.Web.Models.ProductVM.ProductEditViewModel
#{
ViewData["Title"] = "Edit";
}
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<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="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">
<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">
<div class="checkbox">
<label>
<input asp-for="IsActive" /> #Html.DisplayNameFor(model => model.IsActive)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="CategoryId" class="control-label"></label>
<select asp-for="CategoryId" asp-items="Model.CategoryItemList" class="form-control">
<option>Select...</option>
</select>
<span asp-validation-for="CategoryId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Update" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
you have to fix get action
public IActionResult Edit(int id)
{
var prod = _productService.GetById(id);
var categories= _categoryService.GetAll();
var categoryItemList=categories.Select(i=> new SelectListItem
{
Value=i.Id.ToString(),
Text=i.Name
}).ToList();
var model = new ProductEditViewModel
{
Name=prod.Name,
Price= prod.Price,
.... and so on
CategoryItemList = categoryItemList
}
return View(model);
}

MVC - setting up Create.cshtml with related data

I'm quite new to C#, MVC and EF and I've hit a problem I don't seem o be able to resolve.
I'm trying to update the Create.cshtml view so that it shows/lists the itemName rather than itemID where the Item Name is in a different table.
Heres parts of my code so far:
Models:
using System;
using System.Collections.Generic;
namespace CIMSTest.Models
{
public class DirectActivityItem
{
public int ID { get; set; }
public int DirectTypeID { get; set; }
public string ActivityName { get; set; }
public DateTime DateActivityCreated { get; set; }
public bool ActivityLive { get; set; }
public ICollection<DirectActivityGroup> DirectActivityGroups { get; set; }
public DirectType DirectType { get; set; }
}
}
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
namespace CIMSTest.Models
{
public class DirectType
{
public int DirectTypeID { get; set; }
public string DirectTypeName { get; set; }
public bool DirectTypeLive { get; set; }
public ICollection<DirectActivityItem> DirectActivityItems { get; set; }
}
}
Controller (Create):
public IActionResult Create()
{
ViewData["DirectTypeID"] = new SelectList(_context.DirectTypes, "DirectTypeID", "DirectTypeID");
return View();
}
// POST: DirectActivityItems/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,DirectTypeID,ActivityName,DateActivityCreated,ActivityLive")] DirectActivityItem directActivityItem)
{
if (ModelState.IsValid)
{
_context.Add(directActivityItem);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["DirectTypeID"] = new SelectList(_context.DirectTypes, "DirectTypeID", "DirectTypeID", directActivityItem.DirectTypeID);
return View(directActivityItem);
}
Create.cshtml
#model CIMSTest.Models.DirectActivityItem
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>DirectActivityItem</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="DirectTypeID" class="control-label"></label>
<select asp-for="DirectTypeID" class ="form-control" asp-items="ViewBag.DirectTypeID"></select>
</div>
<div class="form-group">
<label asp-for="ActivityName" class="control-label"></label>
<input asp-for="ActivityName" class="form-control" />
<span asp-validation-for="ActivityName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DateActivityCreated" class="control-label"></label>
<input asp-for="DateActivityCreated" class="form-control" />
<span asp-validation-for="DateActivityCreated" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="ActivityLive" /> #Html.DisplayNameFor(model => model.ActivityLive)
</label>
</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");}
}
As you can see the Direct ActivityItem table contains the DirectTypeID, but on the Create page for this I want to list the DirectTypeNames from the DirectType table and not the ID as users won't know what the ID's are.
If anyone can provide any information it would be gratefully received.
Change this:
ViewData["DirectTypeID"] = new SelectList(_context.DirectTypes, "DirectTypeID", "DirectTypeID");
to this:
ViewData["DirectTypeID"] = new SelectList(_context.DirectTypes, "DirectTypeID", "DirectTypeName");
You'll want your view model returning the DirectTypeID since that will be how you best resolve the relationship, but the third parameter tells the SelectList what to display for each selection.

many to many relationship update data mvc .net core

I have a many to many relationship in .net core mvc, but I have no idea how to implement a edit view.
The models are
Studios
public class Studio
{
public int StudioID { get; set; }
public string Name { get; set; }
public ICollection<StudioAddress>StudioAddresses { get; set; }
}
Addresses
public class Address
{
public int AddressID { get; set; }
public string Street { get; set; }
public ICollection<StudioAddress> StudioAddresses { get; set; }
}
StudioAddress
public class StudioAddress
{
public int StudioID { get; set; }
public Studio Studio { get; set; }
public int? AddressID { get; set; }
public Address Address { get; set; }
}
My databasecontext
modelBuilder.Entity<StudioAddress>()
.HasKey(sa => new { sa.StudioID, sa.AddressID });
modelBuilder.Entity<StudioAddress>()
.HasOne(sa => sa.Studio)
.WithMany(s => s.StudioAddresses)
.HasForeignKey(sa => sa.StudioID);
modelBuilder.Entity<StudioAddress>()
.HasOne(sa => sa.Address)
.WithMany(a => a.StudioAddresses)
.HasForeignKey(sa => sa.AddressID);
Now, I have created the edit Get method in my studioscontroller
// get
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var studio = await _context.Studios
.Include(s => s.StudioAddresses).ThenInclude(s => s.Address)
.Where(s => s.StudioID == id)
.AsNoTracking()
.FirstOrDefaultAsync();
if (studio == null)
{
return NotFound();
}
return View(studio);
}
But I have no idea how to update the related data for studio and address?
Bot are forms with textfields. The original microsoft docs are confusing (they work with tickboxes) and weird methods to whitelist fields. Is there a simpler, more intuitive way of doing this?
Based on your model definition, you could try to design the Edit view and the Post method like below :
Here is the “Edit” view:
#model SOMVCDemo.Models.Studio
<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="StudioID" />
<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 class="control-label">StudioAddresses</label>
<table>
<tbody>
#{ int i = 0;}
<tr>
#foreach (var StudioAddress in #Model.StudioAddresses)
{
<td>
<input type="hidden" name="studioAddresses[#i].AddressID" asp-for="#StudioAddress.AddressID" class="form-control" />
<input type="text" name="studioAddresses[#i].Address.Street" asp-for="#StudioAddress.Address.Street" class="form-control" />
</td>
i++;
}
</tr>
</tbody>
</table>
</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>
Here is the POST method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, Studio studio)
{
if (id != studio.StudioID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
var st = _context.Studios.FirstOrDefault(n => n.StudioID == studio.StudioID);
st.Name = studio.Name;
_context.Update(st);
foreach(var i in studio.StudioAddresses)
{
var address = _context.Addresses.FirstOrDefault(n=>n.AddressID == i.AddressID);
address.Street = i.Address.Street;
_context.Update(address);
}
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!StudioExists(studio.StudioID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(studio);
}

ASP MVC 6 RC1 Edit form creates

I have a simple Web application in ASP.NET MVC 6 RC1.
The problem is that when editing a previously added item. The item returned to the Edit POST has an ID = 0, so it creates a copy of the data I was trying to update.
When pressing the Edit link, it takes me to the correct route:
http://localhost:41250/Proyectos/Edit/1
And the GET IActionResult recieves the correct id.
But inside the edit form, when I press the Save button, in the Controller POST part of the Edit it recieves a proyecto who has all the data from the form except the id (ProyectoId) which is 0.
Model:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace RegistroHora.Models
{
public class Proyecto
{
[ScaffoldColumn(false)]
[Key]
public int ProyectoId { get; set; }
[Required]
public string Nombre { get; set; }
[Required]
[Display(Name ="Número de Horas")]
public decimal NumHoras { get; set; }
[Required]
[Display(Name = "Tipo de Horas")]
public string TipoHoras { get; set; }
[Display(Name = "Proyecto Finalizado")]
public bool Concluido { get; set; }
public virtual ICollection<Registro> Registros { get; set; }
}
}
View:
#model RegistroHora.Models.Proyecto
#{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Proyecto</h4>
<hr />
<div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Nombre" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Nombre" class="form-control" />
<span asp-validation-for="Nombre" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="NumHoras" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="NumHoras" class="form-control" />
<span asp-validation-for="NumHoras" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="TipoHoras" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="TipoHoras" class="form-control" />
<span asp-validation-for="TipoHoras" class="text-danger" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkboxs">
<input asp-for="Concluido" type="checkbox"> #Html.DisplayNameFor(i => i.Concluido)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
}
Controller:
using System.Linq;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Data.Entity;
using RegistroHora.Models;
namespace RegistroHora.Controllers
{
public class ProyectosController : Controller
{
private ApplicationDbContext _context;
public ProyectosController(ApplicationDbContext context)
{
_context = context;
}
// GET: Proyectos
public IActionResult Index()
{
return View(_context.Proyecto.ToList());
}
// GET: Proyectos/Details/5
public IActionResult Details(int? id)
{
if (id == null)
{
return HttpNotFound();
}
Proyecto proyecto = _context.Proyecto.Single(m => m.ProyectoId == id);
if (proyecto == null)
{
return HttpNotFound();
}
return View(proyecto);
}
// GET: Proyectos/Create
public IActionResult Create()
{
return View();
}
// POST: Proyectos/Create
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Proyecto proyecto)
{
if (ModelState.IsValid)
{
_context.Proyecto.Add(proyecto);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(proyecto);
}
// GET: Proyectos/Edit/5
public IActionResult Edit(int? id)
{
if (id == null)
{
return HttpNotFound();
}
Proyecto proyecto = _context.Proyecto.Single(m => m.ProyectoId == id);
if (proyecto == null)
{
return HttpNotFound();
}
return View(proyecto);
}
// POST: Proyectos/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Proyecto proyecto)
{
if (ModelState.IsValid)
{
_context.Update(proyecto);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(proyecto);
}
// GET: Proyectos/Delete/5
[ActionName("Delete")]
public IActionResult Delete(int? id)
{
if (id == null)
{
return HttpNotFound();
}
Proyecto proyecto = _context.Proyecto.Single(m => m.ProyectoId == id);
if (proyecto == null)
{
return HttpNotFound();
}
return View(proyecto);
}
// POST: Proyectos/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public IActionResult DeleteConfirmed(int id)
{
Proyecto proyecto = _context.Proyecto.Single(m => m.ProyectoId == id);
_context.Proyecto.Remove(proyecto);
_context.SaveChanges();
return RedirectToAction("Index");
}
}
}
I have NO problem with Index, Create, Delete or Details, only Edit.
You need to pass the ProyectoId value from your form. You may keep that in a hidden field inside your form.
<form asp-action="Edit">
<input type="hidden" asp-for="ProyectoId" />
<!-- Your existing form fields for other properties goes here -->
<input type="submit" value="Save" class="btn btn-default" />
</form>
Another approach is to change signature for method Edit, like this:
public IActionResult Edit(int id, Proyecto proyecto)
In this case, you can pass id over action URL. In this case you need to modify action URL in your view as:
<form asp-action="Edit" asp-route-id=#Model.ProyectoId>
Of cource, you need proper Route that support Id as parametar.
P.s. Id you prefere the first approach, just remove [ScaffoldColumn(false)] from your property class.
Since the update in edit is around the key(ProyectoId); you cannot change it; however instead of making it will disappear by

Categories

Resources