После выполнения табличного запроса, загрузки объекта со свойствами и отправки его обратно в представление я хотел бы обновить некоторые свойства и опубликовать их обратно в таблицу Azure.
У меня есть привязка модели в моем CS-файле страницы Razor следующим образом:
[BindProperty]
public TenantSettingsModel Settings { get; set; }
В моем методе OnGetAsync
я загружаю объект Settings
следующим образом:
public async Task<IActionResult> OnGetAsync()
{
Settings = _azureTableConn.GetTenantSettings(passSomeValue);
return Page();
}
На этом этапе я вижу, что Settings
загружен со свойствами, чтобы вернуться в представление. Я выбираю только несколько свойств для отображения в форме, и я хотел бы отправить обратно эти два изменения (если таковые имеются) вместе с другими неизмененными свойствами в метод OnPostAsync
следующим образом и отобразить представление:
public async Task<IActionResult> OnPostAsync()
{
var response = _azureTableconn.SetTenantSettings(Settings);
return Page();
}
Когда я проверяю объект Settings
, он имеет два свойства формы, но остальные равны нулю. Я мог бы просто установить их вручную, но это кажется пустой тратой.
Можно ли отправить объект с предопределенными свойствами, а затем изменить два из них в форме, но сохранить неизменные свойства, когда он вернется из представления?
Моя единственная другая мысль - создать скрытые элементы формы, чтобы удерживать связанные свойства модели, но если мне нужно это сделать, мне лучше установить это в моем методе OnPostAsync
, я думаю.
Я не видел ваших страниц или кода, но я только что сделал несколько сообщений в CodeProject, которые могут помочь. Похоже, вам может потребоваться использовать элемент формы в файле .cshtml. Атрибут [BindProperty] сделает ваши значения TenantSettingsModel доступными для элементов в вашем пользовательском интерфейсе. Вы можете посмотреть (Страницы Razor ASP.NET Core с использованием EntityFramework Core с перечислениями в виде строк - Часть II)
Здесь я использую Entity Framework Core.
В одном примере я редактирую объект Customer на странице Razor, Edit.cshtml ([Примечание: я использую скрытый ввод для передачи Customer.CustomerId методу PostAsync ()]):
@page
@model QuantumWeb.Pages.Customers.EditModel
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Customer</h4>
<hr />
<div class = "row">
<div class = "col-md-4">
<form method = "post">
<div asp-validation-summary = "ModelOnly" class = "text-danger"></div>
<input type = "hidden" asp-for = "Customer.CustomerId" />
<div class = "form-group">
<label asp-for = "Customer.CustomerName" class = "control-label"></label>
<input asp-for = "Customer.CustomerName" class = "form-control" />
<span asp-validation-for = "Customer.CustomerName"
class = "text-danger"></span>
</div>
<div class = "form-group">
<label asp-for = "Customer.CustomerContact"
class = "control-label"></label>
<input asp-for = "Customer.CustomerContact" class = "form-control" />
<span asp-validation-for = "Customer.CustomerContact"
class = "text-danger"></span>
</div>
<div class = "form-group">
<label asp-for = "Customer.CustomerPhone"
class = "control-label"></label>
<input asp-for = "Customer.CustomerPhone" class = "form-control" />
<span asp-validation-for = "Customer.CustomerPhone"
class = "text-danger"></span>
</div>
<div class = "form-group">
<label asp-for = "Customer.CustomerEmail"
class = "control-label"></label>
<input asp-for = "Customer.CustomerEmail" class = "form-control" />
<span asp-validation-for = "Customer.CustomerEmail"
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-page = "./Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Код программной части Edit.cshtml.cs:
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
public class EditModel : PageModel
{
private readonly QuantumDbContext _context;
public EditModel(QuantumDbContext context)
{
_context = context;
} // end public EditModel(QuantumDbContext context)
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
} // endif (id == null)
Customer =
await _context.Customers
.FirstOrDefaultAsync(m => m.CustomerId == id);
if (Customer == null)
{
return NotFound();
} // endif (Customer == null)
return Page();
} // end public async Task<IActionResult> OnGetAsync(int? id)
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
} // endif (!ModelState.IsValid)
_context.Attach(Customer).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
} // end try
catch (DbUpdateConcurrencyException)
{
if (!CustomerExists(Customer.CustomerId))
{
return NotFound();
}
else
{
throw;
} // endif (!CustomerExists(Customer.CustomerId))
} // end catch (DbUpdateConcurrencyException)
return RedirectToPage("./Index");
} // end public async Task<IActionResult> OnPostAsync()
private bool CustomerExists(int id)
{
return _context.Customers.Any(e => e.CustomerId == id);
} // end private bool CustomerExists(int id)
} // end public class EditModel : PageModel
} // end namespace QuantumWeb.Pages.Customers
Надеюсь, это поможет.
У меня есть другие части в моем сообщении CodeProject (части III и IV), которые используют Entity Framework для загрузки связанных данных в GET. ([Страницы Razor ASP.NET Core с использованием EntityFramework Core с перечислениями в виде строк - Часть III и Страницы Razor ASP.NET Core с использованием EntityFramework Core с перечислениями в виде строк - Часть IV)
В части IV у меня есть страница CustomerProjectSkillAssign.cshtml:
@page "{id:int?}"
@model QuantumWeb.Pages.Customers.CustomerProjectSkillAssignModel
@{
ViewData["Title"] = "Customer Project Skill Assignment";
}
<h2>Customer Project Skill Assignment</h2>
<hr />
<dl class = "dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Project.ProjectId)
</dt>
<dd>
@Html.DisplayFor(model => model.Project.ProjectId)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Project.ProjectName)
</dt>
<dd>
@Html.DisplayFor(model => model.Project.ProjectName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerId)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerId)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Customer.CustomerName)
</dt>
<dd>
@Html.DisplayFor(model => model.Customer.CustomerName)
</dd>
</dl>
<div class = "row">
<div class = "col-md-4">
<form method = "post">
<div asp-validation-summary = "ModelOnly" class = "text-danger"></div>
<input type = "hidden" asp-for = "Project.ProjectId" />
<div class = "form-group">
<label asp-for = "SkillTitle.SkillCode" class = "control-label"></label>
<select asp-for = "SkillTitle.SkillCode" class = "form-control" asp-items = "ViewBag.SkillCode"></select>
</div>
<div class = "form-group">
<a asp-page = "./CustomerProjectSkills" asp-route-id = "Project.ProjectId">Project Skills</a> |
<input type = "submit" value = "Assign" class = "btn btn-default" />
</div>
</form>
</div>
</div>
Обратите внимание, что у меня есть только один скрытый элемент управления с Project.ProjectId. CustomerProjectSkillAssign.cshtml.cs:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using QuantumWeb.Data;
using QuantumWeb.Model;
namespace QuantumWeb.Pages.Customers
{
public class CustomerProjectSkillAssignModel : PageModel
{
private readonly QuantumDbContext _context;
public CustomerProjectSkillAssignModel(QuantumDbContext context)
{
_context = context;
} // end public CustomerProjectSkillAssignModel(QuantumDbContext context)
[BindProperty]
public Project Project { get; set; }
[BindProperty]
public Customer Customer { get; set; }
[BindProperty]
public SkillTitle SkillTitle { get; set; }
public async Task<IActionResult> OnGet(int? id)
{
if (id == null)
{
return NotFound();
} // endif (id == null)
Project = await _context.Projects
.Include(p => p.Customer)
.Include(p => p.ProjectSkills)
.ThenInclude(ps => ps.SkillTitle)
.FirstOrDefaultAsync(p => p.ProjectId == id);
if (Project == null)
{
return NotFound();
} // endif (Project == null)
Customer = Project.Customer;
ViewData["SkillCode"] = new SelectList(_context.SkillTitles, "SkillCode", "Title");
return Page();
}// end public async Task<IActionResult> OnGet(int? id)
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
} // endif (!ModelState.IsValid)
ProjectSkill projectSkill = new ProjectSkill()
{
ProjectId = Project.ProjectId,
SkillCode = SkillTitle.SkillCode
};
_context.ProjectSkills.Add(projectSkill);
await _context.SaveChangesAsync();
return RedirectToPage("./CustomerProjectSkills", new { id = Project.ProjectId });
} // end public async Task<IActionResult> OnPostAsync()
} // end public class CustomerProjectSkillAssignModel : PageModel
} // end namespace QuantumWeb.Pages.Customers
Активная загрузка извлекает объект Project и его объект Customer, а также его коллекцию ProjectSkills. У каждого ProjectSkill есть SkillTitle. Кроме того, я загружаю коллекцию доступных объектов SkillTitle в выпадающий список. Выбранный элемент передается в OnPostAsync () через форму. Однако есть только один скрытый элемент управления, указывающий на целевой проект.
У меня аналогичная проблема, и я не уверен, что мой подход правильный. Вместо того, чтобы отображать данные (подлежащие редактированию) в DIV, я показываю их в ТАБЛИЦЕ. Я могу понять, как скрытое свойство обновляет строку. В моем случае я показываю несколько строк на странице редактирования, но не могу обновить базу данных только для тех строк, которые имеют обновления.
Моя страница просмотра такая
<form method = "post">
<div asp-validation-summary = "ModelOnly" class = "text-danger"></div>
<table class = "table">
<thead>
<tr>
<th> @Html.DisplayNameFor(model => model.Fields[0].Name) </th>
<th> @Html.DisplayNameFor(model => model.Fields[0].Value) </th>
<th> @Html.DisplayNameFor(model => model.Fields[0].Confidence) </th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Fields)
{
<tr>
<td> <input type = "hidden" [email protected] /> </td>
<td> @Html.DisplayFor(modelItem => item.Name) </td>
<td contenteditable='true'> @Html.DisplayFor(modelItem => item.Value) </td>
<td> @Html.DisplayFor(modelItem => item.Confidence) </td>
</tr>
}
</tbody>
</table>
<div class = "form-group">
<input type = "submit" value = "Save" class = "btn btn-primary" />
</div>
</form>
И код, стоящий за этим, таков. Поля показывают 0 в методе OnPostAsync.
[BindProperty]
public IList<FieldInfo> Fields { get; set; }
public async Task<IActionResult> OnGetAsync(string id)
{
if (id == null)
{
return NotFound();
}
Fields = await _context.FieldInfo.Where(m => m.GUID == id).ToListAsync();
if (Fields == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
foreach (var p in Fields) // In this approach Fields shows as count=0
{
_context.Attach(p.Value).State = EntityState.Modified;
}
_context.Attach(Fields).State = EntityState.Modified; // In this approach Exception: The entity type 'List<FieldInfo>' was not found.
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
Да, похоже, если вы дадите странице скрытое свойство для каждого входящего элемента, вы можете вытащить их в методе
post
, обратившись к объекту по имени.