В свободное время я работаю над веб-приложением, чтобы выучить EF6, и использовал учебник, использованный с https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application.
У меня есть полностью работающее приложение, созданное на основе этого учебного пособия, и я понимаю, что большинство из них воссоздают его вручную. Однако я столкнулся с проблемой при создании функции редактирования.
В моем случае, эта функция редактирования редактирует название и категорию ингредиента, но ни одна из них не изменяется. Даже если я напрямую скопирую код из учебника, он не будет работать.
К сожалению, при попытке поймать ошибки не выдаются. Я даже пытался использовать UpdateModel вместо TryUpdateModel, но это тоже ничего не дает. Я предполагаю, что это означает, что это работает, но мои строки никак не редактируются. Я пытался изменить свой код несколько раз, но безрезультатно.
Контроллер:
// PUT: Ingredient/
[HttpPut, ActionName("Index")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EditIngredient(int? id, byte[] rowVersion)
{
string[] fieldsToBind = new string[] { "Name", "Category", "RowVersion" };
var ingredients = db.Ingredients.Select(i => i).OrderBy(s => s.Name);
var categories = db.IngredientCategories;
var ingredientIndexViewModel = new IngredientIndex
{
ingredients = await ingredients.ToPagedListAsync(1, MaxIngredientsPerPage),
categories = await categories.ToListAsync()
};
if (id == null)
{
ErrorMessage = "No id found to update.";
return View(ingredientIndexViewModel);
}
// Try and find the ingredient we're trying to update. If we haven't found anything, it's removed.
var ingredientToUpdate = await db.Ingredients.FindAsync(id);
if (ingredientToUpdate == null)
{
ErrorMessage = "Unable to save changes. The ingredient was deleted by another user.";
return RedirectToAction("Index");
}
if (!TryUpdateModel(ingredientToUpdate, fieldsToBind))
{
ErrorMessage = "Unable to update model.";
return RedirectToAction("Index");
}
try
{
// Try updating the row in the database.
db.Entry(ingredientToUpdate).OriginalValues["RowVersion"] = rowVersion;
await db.SaveChangesAsync();
}
// Concurrency error (rowversion doesn't match DB rowversion)
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (Ingredient)entry.Entity;
clientValues.Category = await db.IngredientCategories.FindAsync(clientValues.CategoryId);
// Add the original vlaues to the information modals
ModelState.AddModelError("NameValidation", $"Current value: { ingredientToUpdate.Name }");
ModelState.AddModelError("CategoryValidation", $"Current value: { ingredientToUpdate.Category.Name }");
ErrorMessage = @"The record you attempt to edit has been modified by another user during your session.<br/>
The original values have been added next to the input for reference.<br/>
If you still want to edit this record, then press the ""Edit"" button again.";
// Update the rowversion for the next edit. The user is fully aware now so he can update if he wants.
ingredientToUpdate.RowVersion = ingredientToUpdate.RowVersion;
// Add the form ingredient for display
ingredientIndexViewModel.ingredient = clientValues;
return View(ingredientIndexViewModel);
}
catch (RetryLimitExceededException)
{
ErrorMessage = "Unable to save changes. Try again, and if the problem persists, see your system administrator.";
return View(ingredientIndexViewModel);
}
SuccessMessage = $"{ingredientToUpdate.Name} has been updated.";
return RedirectToAction("Index");
}
Модель:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Site.Models
{
public class Ingredient
{
public int Id { get; set; }
[StringLength(50, MinimumLength = 2, ErrorMessage = "Make sure the name of your ingredient is between {2} and {1} characters.")]
[Required(ErrorMessage = "Please insert a valid name for your ingredient.")]
[Index(IsUnique = true)]
public string Name { get; set; }
[DisplayFormat(NullDisplayText = "No category")]
public IngredientCategory Category { get; set; }
public int CategoryId { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Date added")]
public DateTime Date_Added { get; set; } = DateTime.Now;
[Timestamp]
public byte[] RowVersion { get; set; }
}
public class IngredientCategory
{
public int Id { get; set; }
[StringLength(50, MinimumLength = 2, ErrorMessage = "Make sure the category is between {2} and {1} characters.")]
[Required(ErrorMessage = "Please insert a valid category.")]
[Index(IsUnique = true)]
[Display(Name = "Category")]
public string Name { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
}
ViewModel:
using System.Collections.Generic;
using Site.Models;
using PagedList;
namespace Site.ViewModels
{
public class IngredientIndex
{
// Create / edit
public Ingredient ingredient { get; set; }
// List
public IPagedList<Ingredient> ingredients { get; set; }
public List<IngredientCategory> categories { get; set; }
}
}
Ожидаемый результат будет рабочим методом. По крайней мере TryUpdateModel / UpdateModel вернет ошибку, но я не могу найти никаких ошибок. Если это помогает, кажется, что clientValues
получает значения базы данных, а не значения клиента. Он должен получить клиентские значения, чтобы заполнить форму ими, но вместо этого принимаются значения базы данных.