Add comments in Detail View ASP.NET Core - c#

I tried to add a comment in Detail View, but it doesn't work when I input some text in TextArea. Throwing NullReferenceException in
if (id != ticket.TicketId)
{
return NotFound();
}
I created ViewModel -> contain (Ticket and Comment)
<div class="form-group">
<form asp-action="Details">
<label asp-for="Comment" class="control-label"></label>
<textarea asp-for="Comment.Content" class="form-control" placeholder="Add comment!"></textarea>
<span asp-validation-for="Comment.Content" class="text-danger"></span>
<input type="submit" value="Add comment" class="btn btn-default" />
</form>
</div>
Here is an example how I try to provide some text, bind to Comment, and here is my Detail method in Controller:
public async Task<IActionResult> Details(int id, TicketCommentViewModel model)
{
var ticket = model.Ticket;
if (id != ticket.TicketId)
{
return NotFound();
}
var oldTicket = await _context.Tickets.SingleOrDefaultAsync(t => t.TicketId == ticket.TicketId);
var comment = new Comment();
var user = await GetCurrentUserAsync();
oldTicket.Comments.Add(comment);
comment.Content = model.Comment.Content;
comment.SendTime = DateTime.Now;
comment.TicketID = ticket.TicketId;
comment.Ticket = ticket;
comment.UserId = user.Id;
comment.User = user;
if (ModelState.IsValid)
{
try
{
await _context.Comments.AddAsync(comment);
_context.Update(oldTicket);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TicketExists(oldTicket.TicketId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(model);
}

Related

The model item passed into the ViewDataDictionary is of type '...', but this ViewDataDictionary instance requires a model item of type '...'

What am I doing?
I am trying using two modal in one view.
What's the problem?
When run give this error:
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'ProgramaEstagio.Models.Person', but this ViewDataDictionary instance requires a model item of type 'ProgramaEstagio.Models.RegisterViewModel'.
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(object value)
Part of "PersonController.cs":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ProgramaEstagio.Data;
using ProgramaEstagio.Models;
namespace ProgramaEstagio.Controllers
{
public class PersonController : Controller
{
private readonly ApplicationDbContext _context;
public PersonController(ApplicationDbContext context)
{
_context = context;
}
// GET: Person
public async Task<IActionResult> Index()
{
return View(await _context.Person.ToListAsync());
}
// GET: Person/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var person = await _context.Person.FindAsync(id);
if (person == null)
{
return NotFound();
}
return View(person);
}
// POST: Person/Edit/5
// 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> Edit(int id, [Bind("ID,FullName,BirthDate,sex")] Person person)
{
if (id != person.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(person);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PersonExists(person.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(person);
}
RegisterViewModel.cs:
namespace ProgramaEstagio.Models
{
public class RegisterViewModel
{
public Person Person { get; set; }
public Address Address { get; set; }
}
}
Edit.cshtml:
#model ProgramaEstagio.Models.RegisterViewModel
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Person</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="Person.ID" />
<div class="form-group">
<label asp-for="Person.FullName" class="control-label"></label>
<input asp-for="Person.FullName" class="form-control" />
<span asp-validation-for="Person.FullName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Person.BirthDate" class="control-label"></label>
<input asp-for="Person.BirthDate" class="form-control" />
<span asp-validation-for="Person.BirthDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Person.sex" class="control-label"></label>
<input asp-for="Person.sex" class="form-control" />
<span asp-validation-for="Person.sex" class="text-danger"></span>
</div>
<h4>Address</h4>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Address.ID" />
<div class="form-group">
<label asp-for="Address.Country" class="control-label"></label>
<input asp-for="Address.Country" class="form-control" />
<span asp-validation-for="Address.Country" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.Complement" class="control-label"></label>
<input asp-for="Address.Complement" class="form-control" />
<span asp-validation-for="Address.Complement" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.Distric" class="control-label"></label>
<input asp-for="Address.Distric" class="form-control" />
<span asp-validation-for="Address.Distric" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.City" class="control-label"></label>
<input asp-for="Address.City" class="form-control" />
<span asp-validation-for="Address.City" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.State" class="control-label"></label>
<input asp-for="Address.State" class="form-control" />
<span asp-validation-for="Address.State" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.PersonID" class="control-label"></label>
<select asp-for="Address.PersonID" class="form-control" asp-items="ViewBag.PersonID"></select>
<span asp-validation-for="Address.PersonID" 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");}
}
What I have to do? please help me. If need more information, ask please. And sorry for any error orthography and grammar I am studing English.
Project Link: https://github.com/vitorhugo1207/Sys-Vacina/tree/EditPagePersonAdress
Edit:
AddressController.cs:
// GET: Addresse/Edit/5
public async Task<IActionResult> Edit(int? id)
{
RegisterViewModel register = new RegisterViewModel();
if (id == null)
{
return NotFound();
}
var address = await _context.Address.FindAsync(id);
if (address == null)
{
return NotFound();
}
ViewData["PersonID"] = new SelectList(_context.Person, "ID", "FullName", address.PersonID);
register.Address = address;
return View(register);
}
// POST: Addresse/Edit/5
// 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> Edit(int id, [Bind("ID,Country,Complement,Distric,City,State,PersonID")] Address address)
{
if (id != address.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(address);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AddressExists(address.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["PersonID"] = new SelectList(_context.Person, "ID", "FullName", address.PersonID);
return View(address);
}
It is happening on this line: return View(person);. You are sending a Model of type Person but you need to send a Model of RegisterViewModel. You need to send the correct Model to your View:
public async Task<IActionResult> Edit(int? id)
{
RegisterViewModel register = new RegisterViewModel();
if (id == null)
{
return NotFound();
}
var person = await _context.Person.FindAsync(id);
if (person == null)
{
return NotFound();
}
register.Person = person;
var address = await _context.Address.FindAsync(id);
if (address == null)
{
return NotFound();
}
register.Address = address;
return View(register);
}
You essentially made a promise to C# that you would send a model of type RegisterViewModel, when you wrote this:
#model ProgramaEstagio.Models.RegisterViewModel
But then you actually sent a Person instead:
var person = await _context.Person.FindAsync(id);
...
return View(person);
It doesn't really matter what these two things are, so long as they agree; if you upgrade/change the type in one place (like the cshtml), you have to change it everywhere else (like the controller View(..) calls) to ensure they remain in agreement with each other

How to update record consisting of dependent tables using ASP.NET Core [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed last year.
Improve this question
I can list and create records, but can't update the records. When I run my project and click the Edit button on listed records, form page appears, but if I click Submit after completing the form, I get page not found error in same URL.
I can list and create records, but can't update the records. When I run my project and click the Edit button on listed records, form page appears, but if I click Submit after completing the form, I get page not found error in same URL.
CustomerAddressModel
namespace PharmacyManagmentV2.Models
{
public class CustomerAdressModel
{
public Customer customer { get; set; }
public Address address { get; set; }
}
}
CustomerController
namespace PharmacyManagmentV2.Areas.Application.Controllers
{
[Area("Application")]
public class CustomerController : Controller
{
private readonly AppDBContext _context;
private readonly IGenericRepository<Address> _address;
private readonly IGenericRepository<Customer> _customer;
public CustomerController(AppDBContext context,
IGenericRepository<Address> address,
IGenericRepository<Customer> customer)
{
_context = context;
_address = address;
_customer = customer;
}
// GET: Application/Customer
public async Task<IActionResult> Index()
{
var appDBContext = _customer.GetAll().Include(c => c.Address);
return View(await appDBContext.ToListAsync());
}
// GET: Application/Customer/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var model = new CustomerAdressModel();
model.customer = await _customer.GetAll()
.Include(c => c.Address)
.FirstOrDefaultAsync(m => m.Id == id);
model.address = await _address.GetAll()
.Include(m => m.AspNetUsers)
.FirstOrDefaultAsync(m => m.Id == model.customer.AddressId);
if (model.customer == null)
{
return NotFound();
}
return View(model);
}
// GET: Application/Customer/Create
public IActionResult Create()
{
return View();
}
// POST: Application/Customer/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(CustomerAdressModel model)
{
if (ModelState.IsValid)
{
await _address.Create(model.address);
await _customer.Create(new Customer()
{
Address = model.address
});
await _address.SaveChanges();
await _customer.SaveChanges();
return RedirectToAction(nameof(Index));
}
return View(model);
}
// GET: Application/Customer/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var model = new CustomerAdressModel();
model.customer = await _customer.GetById(id.Value);
model.address = await _address.GetById(model.customer.AddressId.Value);
if (model.customer == null)
{
return NotFound();
}
return View(model);
}
// POST: Application/Customer/Edit/5
// 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> Edit(int id, CustomerAdressModel model)
{
if (id != model.customer.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
await _customer.Update(model.customer);
await _customer.SaveChanges();
await _address.Update(model.address);
await _address.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!CustomerExists(model.customer.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(model);
}
// GET: Application/Customer/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var customer = await _context.Customers
.Include(c => c.Address)
.FirstOrDefaultAsync(m => m.Id == id);
if (customer == null)
{
return NotFound();
}
return View(customer);
}
// POST: Application/Customer/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var customer = await _context.Customers.FindAsync(id);
_context.Customers.Remove(customer);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool CustomerExists(int id)
{
return _context.Customers.Any(e => e.Id == id);
}
}
}
Edit.cshtml
#model PharmacyManagmentV2.Models.CustomerAdressModel
#{
ViewData["Title"] = "Edit";
Layout = "~/Areas/Application/Views/Shared/_Layout.cshtml";
}
<h1>Edit</h1>
<h4>CustomerViewModel</h4>
<hr />
<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="#Model.customer.FirstName" class="control-label"></label>
<input asp-for="#Model.customer.FirstName" class="form-control" />
<span asp-validation-for="#Model.customer.FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.customer.LastName" class="control-label"></label>
<input asp-for="#Model.customer.LastName" class="form-control" />
<span asp-validation-for="#Model.customer.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.customer.Email" class="control-label"></label>
<input asp-for="#Model.customer.Email" class="form-control" />
<span asp-validation-for="#Model.customer.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.customer.Balance" class="control-label"></label>
<input asp-for="#Model.customer.Balance" class="form-control" />
<span asp-validation-for="#Model.customer.Balance" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.customer.Gender" class="control-label"></label>
<input asp-for="#Model.customer.Gender" class="form-control" />
<span asp-validation-for="#Model.customer.Gender" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.customer.DateofBird" class="control-label"></label>
<input asp-for="#Model.customer.DateofBird" class="form-control" />
<span asp-validation-for="#Model.customer.DateofBird" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.customer.Phone" class="control-label"></label>
<input asp-for="#Model.customer.Phone" class="form-control" />
<span asp-validation-for="#Model.customer.Phone" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.address.City" class="control-label"></label>
<input asp-for="#Model.address.City" class="form-control" />
<span asp-validation-for="#Model.address.City" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.address.State" class="control-label"></label>
<input asp-for="#Model.address.State" class="form-control" />
<span asp-validation-for="#Model.address.State" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.address.Zip" class="control-label"></label>
<input asp-for="#Model.address.Zip" class="form-control" />
<span asp-validation-for="#Model.address.Zip" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.address.Address1" class="control-label"></label>
<input asp-for="#Model.address.Address1" class="form-control" />
<span asp-validation-for="#Model.address.Address1" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.address.Address2" class="control-label"></label>
<input asp-for="#Model.address.Address2" class="form-control" />
<span asp-validation-for="#Model.address.Address2" 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");}
}
Startup.cs
namespace PharmacyManagmentV2
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddControllersWithViews();
string connectionString = Configuration.GetConnectionString("default");
services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));
services.AddIdentity<ApplicationUser, ApplicationRole>(opt =>
{
opt.Password.RequireDigit = false;
opt.Password.RequireLowercase = false;
opt.Password.RequiredLength = 1;
opt.Password.RequireUppercase = false;
opt.Password.RequireNonAlphanumeric = false;
}).AddEntityFrameworkStores<AppDBContext>();
services.ConfigureApplicationCookie(opt =>
{
opt.Cookie.Name = "CookieSettings";
opt.LoginPath = new PathString("/Account/Login");
opt.Cookie.HttpOnly = true;
opt.Cookie.SameSite = SameSiteMode.Strict;
opt.ExpireTimeSpan = TimeSpan.FromMinutes(30);
});
services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme,
opt =>
{
opt.Cookie.Name = "CookieSettings";
opt.LoginPath = new PathString("/Account/Login");
opt.Cookie.HttpOnly = true;
opt.Cookie.SameSite = SameSiteMode.Strict;
opt.ExpireTimeSpan = TimeSpan.FromMinutes(30);
});
services.AddScoped<IAddressRepository, AddressRepository>();
services.AddScoped<ICategoryRepository, CategoryRepository>();
services.AddScoped<ICustomerRepository, CustomerRepository>();
services.AddScoped<ILeafRepository, LeafRepository>();
services.AddScoped<IManufacturerRepository, ManufacturerRepository>();
services.AddScoped<IMedicineRepository, MedicineRepository>();
services.AddScoped<IMedicineTypeRepository, MedicineTypeRepository>();
services.AddScoped<IPurchaseRepository, PurchaseRepository>();
services.AddScoped<ISellRepository, SellRepository>();
services.AddScoped<IUnitRepository, UnitRepository>();
services.AddScoped(typeof(IGenericRepository<>),typeof(GenericRepository <>));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{area=Application}/{controller=Customer}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "Login",
pattern: "{controller=Account}/{action=Login}/{id?}");
endpoints.MapControllerRoute(
name: "Register",
pattern: "{controller=Account}/{action=Login}/{id?}");
endpoints.MapControllerRoute(
name: "application_home",
pattern: "{area=Application}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "customer_list",
pattern: "{area=Application}/{controller=Customer}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "customer_edit",
pattern: "{area=Application}/{controller=Customer}/{action=Edit}/{id?}");
});
}
}
}
Since you are using [ValidateAntiForgeryToken] at your action try to add
#Html.AntiForgeryToken()
<form asp-action="Edit" >
#Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
or remove [ValidateAntiForgeryToken]

ASP.NET MVC: Method for HttpPost is not executed

In an ASP.NET MVC application, I have a file MessageController.cs where I define EditMessage for access via HttpGet and HttpPost. Usually the user first accesses it via HttpGet, then a form pops up where he can edit the message, and then he clicks on the Save button, by which HttpPost will be invoked.
My problem is that HttpPost is not invoked. Instead, an error message is displayed. I have analogous code for modifying other parts of the database and with that analogous code, HttpPost works. My question is why it does not work here and what I can do to make it work.
/// <summary>
/// used by admin only
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[CustomAuthorization(new[] { GlobalStaticFunc.SecurityOptions.isSUser, GlobalStaticFunc.SecurityOptions.isAdmin })]
[HttpGet]
public async Task<ActionResult> EditMessage(int id)
{
if (PopupController.AnyPopupsInline(User))
{
return RedirectToAction("index", "popup");
}
if (id > 0)
{
BLogic_Entity dbContext = new VMIEntityCreator(true);
var msg = dbContext.GetDbSet<MSG_MESSAGES>().Where(x => x.id == id).FirstOrDefault();
if (msg != null) return View(msg);
}
else if (id == -1)
{
return View(new MSG_MESSAGES() { id = -1 });
}
return View("Messages");
}
[CustomAuthorization(new[] { GlobalStaticFunc.SecurityOptions.isCarrier, GlobalStaticFunc.SecurityOptions.isAdmin, GlobalStaticFunc.SecurityOptions.isSUser })]
[HttpPost]
// [ValidateAntiForgeryToken]
public async Task<ActionResult> EditMessage(MSG_MESSAGES model)
{
if (PopupController.AnyPopupsInline(User))
{
return RedirectToAction("index", "popup");
}
if (!App_Tools.RightsHandler.IdentityWatcher.CheckUserRights(User.Identity, GlobalStaticFunc.SecurityOptions.isAdmin) && App_Tools.RightsHandler.IdentityWatcher.CheckUserRights(User.Identity, GlobalStaticFunc.SecurityOptions.isEndUser))
{
return RedirectToAction("Messages", "Message");
}
bool isOk = false;
if (model != null)
{
if (!ModelState.IsValid)
{
return View(model);
}
if (model.id > 0)
{
using (TED_BLOGIC.Abstractions.BLogic_Entity usr = new VMIEntityCreator(true))
{
isOk = await usr.UpdateSecurely(usr.GetDbSet<MSG_MESSAGES>().Where(x => x.id == model.id).FirstOrDefault(), model, ModelState);
}
}
}
return View(model);
}
The code of EditMessage.cshtml:
#model TED_BLOGIC.DataBase.DB_MODEL.MSG_MESSAGES
#{
if (Model != null && Model.id > 0)
{
ViewBag.Title = "Message bearbeiten";
}
else
{
ViewBag.Title = "Neue Message anlegen";
}
ViewBag.Ico = "fa-plus";
Layout = "~/Views/Shared/_standardBoxView.cshtml";
}
#using (Html.BeginForm("EditMessage", "Message", new { id = Model.id }, FormMethod.Post, new { data_goback = true }))
{
#Html.AntiForgeryToken()
<div class="panel-body">
<div class="row">
<div class="col-md-12 table-responsive">
#Html.ValidationSummary(false, "", new { #class = "text-danger" })
#Html.EditorForModel("Add/MGV")
<div class="section row mb10">
<div class="form-group">
<div class="col-md-offset-2 col-lg-3 col-md-4 col-sm-5">
<input type="submit" value="Save" class="btn btn-default" onclick=";" /> #*mCust.postToSite(#Url.Action("User", "Admin"));mCust.sendMeBack()*#
</div>
</div>
</div>
</div>
</div>
</div>
}
<script src="~/Scripts/Core/PostbackHandling/OverwritePostbacks.js?v=#GlobalStaticFunc.Version"></script>
<script>
$(document).on("EverythingIsReady", function () {
document.title = 'Cloud - #ViewBag.Title';
})
</script>
<input type="submit" value="Save" class="btn btn-default" onclick=";" />
Could you please try removing onclick attribute of the button?
please check by commenting CustomAuthorization attribute above that post method, the post-event will be fired. I tested your code.

ASP.NET MVC Core Error -> DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s)

I know there are a few questions of this error posted but none of them helped me!
I'm using ASP.NET MVC Core and Identiy and I'm trying to update Roles. But it's getting a bit nerve wrecking because I can't find out what's the problem with my code.
The error is the following:
DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
screen of the error is display here
My controller:
public async Task<IActionResult> Edit(string id)
{
if (id == null)
{
return NotFound();
}
//var role = await roleManager.FindByIdAsync(id);
var role = await roleManager.Roles.FirstOrDefaultAsync(f => f.Id == id);
if (role == null)
{
return NotFound();
}
return View(role);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("Id,Name")] IdentityRole role)
{
if (id != role.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Entry(role).State = EntityState.Modified;
await roleManager.UpdateAsync(role);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbConcurrencyException ex)
{
throw new DbConcurrencyException(ex.Message);
}
}
return View(role);
}
My View :
#model Microsoft.AspNetCore.Identity.IdentityRole
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Roles</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="#Model.Id" />
<div class="form-group">
<label asp-for="#Model.Name" class="control-label"></label>
<input asp-for="#Model.Name" class="form-control" />
<span asp-validation-for="#Model.Name" 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");}
}
I would really appreciate some help getting this error fixed.
Your code is not correct. replace this:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit([Bind("Id,Name")] IdentityRole role)
{
if (ModelState.IsValid)
{
var roleItem = await _roleManager.FindByIdAsync(role.Id);
if (roleItem != null)
{
roleItem.Name = role.Name;
var updateResult = await _roleManager.UpdateAsync(roleItem);
if (updateResult.Succeeded)
{
return RedirectToAction(nameof(Index));
}
else
{
//Handle errors
}
}
else
{
//Handle errors
}
}
return View(role);
}

Url seems to be repeating

I am using asp.net razor engine. I have a delete button and the first time I press it, it works. The second time the url repeats the function and does not work.
This is the first time I use the Delete button
This is the second time I use Delete. Notice the URL is del/del. Trying to avoid that second del.
Here is my controller
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using DapperApp.Factory;
using login.Models;
using login.Controllers;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Http;
namespace login.Controllers
{
public class HomeController : Controller
{
private readonly UserFactory userFactory;
public HomeController(UserFactory user) {
userFactory = user;
}
// GET: /Home/
[HttpGet]
[Route("")]
public IActionResult Index()
{
return View();
}
[HttpPost]
[Route("")]
public IActionResult Register(Home model)
{
if(!ModelState.IsValid)
{
return View("Index", model);
}
PasswordHasher<Home> Hasher = new PasswordHasher<Home>();
model.Password = Hasher.HashPassword(model, model.Password);
userFactory.Add(model);
TempData["message"] = false;
return RedirectToAction("Index");
}
[HttpPost]
[Route("login")]
public IActionResult Login(Home model)
{
if(model.Password == null || model.Email == null){
TempData["login"] = false;
return RedirectToAction("Index");
}
var pass = userFactory.FindByEmail(model);
var Hasher = new PasswordHasher<Home>();
if(pass == null)
{
TempData["login"] = false;
return RedirectToAction("Index");
}
// Pass the user object, the hashed password, and the PasswordToCheck
if(0 != Hasher.VerifyHashedPassword(model, pass.Password, model.Password))
{
TempData["first_name"] = pass.First_Name;
TempData["last_name"] = pass.Last_Name;
TempData["id"] = pass.Id;
HttpContext.Session.SetString("Id", pass.Id.ToString());
ViewBag.Quotes = userFactory.FindAll();
return View();
}
TempData["login"] = false;
return RedirectToAction("Index");
}
[HttpPost]
[Route("addQuote")]
public IActionResult AddQuote(Quotes model)
{
var test = HttpContext.Session.GetString("Id");
if(!ModelState.IsValid)
{
TempData["id"] = test;
model.Users_id = Convert.ToInt32(test.ToString());
var user2 = userFactory.FindById(model.Users_id);
TempData["first_name"] = user2.First_Name;
TempData["last_name"] = user2.Last_Name;
ViewBag.Quotes= userFactory.FindAll();
return View("Login", model);
}
if(test == null){
return RedirectToAction("Index");
}
model.Users_id = Convert.ToInt32(test.ToString());
userFactory.addQuote(model);
var user = userFactory.FindById(model.Users_id);
TempData["id"] = test;
TempData["first_name"] = user.First_Name;
TempData["last_name"] = user.Last_Name;
ViewBag.Quotes = userFactory.FindAll();
return View("Login", model);
}
[HttpGet]
[Route("logout")]
public IActionResult Logout()
{
return RedirectToAction("Index");
}
[HttpGet]
[Route("del/{id}")]
public IActionResult Del(int Id) // This is my delete method
{
userFactory.DeleteByID(Id);
ViewBag.Quotes2= userFactory.FindAll();
var test = HttpContext.Session.GetString("Id");
var user = userFactory.FindById(Convert.ToInt32(test));
TempData["first_name"] = user.First_Name;
TempData["last_name"] = user.Last_Name;
TempData["id"] = test;
return View("Login");
}
}
}
Here is my cshtml page
<h1>Hello #TempData["first_name"] #TempData["last_name"]</h1>
#if(TempData["first_name"]!= null)
{
}
#model login.Models.Quotes
<h1>Add Your Quote</h1>
#using(Html.BeginForm("AddQuote","Home"))
{
<p>
<label>Your Quote</label>
#Html.TextAreaFor(d=>d.quotes)
#Html.ValidationMessageFor(d => d.quotes)
</p>
<input type="submit" name="submit" value="Add my quote!"/>
}
<form action="logout" method="get">
<input type="submit" name="submit" value="Log Out"/>
</form>
<div >
#{
if(ViewBag.Quotes != null)
{
foreach(var quotes in ViewBag.Quotes)
{
//If there are any errors for a field...
<p><q>#quotes.quotes</q></p>
<p class="wrapper">-#quotes.First_Name #quotes.Last_Name at #quotes.Created_At.ToString("hh"):#quotes.Created_At.ToString("mm")
#quotes.Created_At.ToString("tt") #quotes.Created_At.ToString("MMM") #quotes.Created_At.ToString("dd")
#quotes.Created_At.ToString("yyyy")</p>
if(#quotes.Users_id == Convert.ToInt32(TempData["id"].ToString()))
{
<form action="del/#quotes.Id_Quotes" method="get">
<input type="submit" name="submit" value="Delete"/>
</form>
}
}
}
if(ViewBag.Quotes2 != null)
{
foreach(var quotes in ViewBag.Quotes2)
{
//If there are any errors for a field...
<p><q>#quotes.quotes</q></p>
<p class="wrapper">-#quotes.First_Name #quotes.Last_Name at #quotes.Created_At.ToString("hh"):#quotes.Created_At.ToString("mm")
#quotes.Created_At.ToString("tt") #quotes.Created_At.ToString("MMM") #quotes.Created_At.ToString("dd")
#quotes.Created_At.ToString("yyyy")</p>
if(#quotes.Users_id == Convert.ToInt32(TempData["id"].ToString()))
{
<form action="del/#quotes.Id_Quotes" method="get">
<input type="submit" name="submit" value="Delete"/>
</form>
}
}
}
}
</div>
Your form action is using a relative (not a concrete) reference, meaning it will append the action to the end of the current url each time you submit the form. Try making the action the absolute url of your get request. In this case that would mean:
<form action="del/#quotes.Id_Quotes" method="get">
<input type="submit" name="submit" value="Delete"/>
</form>
becomes
<form action="/del/#quotes.Id_Quotes" method="get">
<input type="submit" name="submit" value="Delete"/>
</form>
Also, just to nitpick, when deleting things (or adding and editing things) to a database you should use a POST request. They provide an additional level of security.

Categories