使用Razor Pages发送已加载的对象以进行查看并从POST获取更改

时间:2018-10-28 15:33:41

标签: c# razor asp.net-core razor-pages

执行表查询,加载具有属性的对象并将其发送回视图后,我想更新一些属性并将其发布回Azure表。

我的Razor Page cs文件中具有模型绑定,如下所示:

[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对象时,它具有两个表单属性,但其他属性为null。我可以简单地手动设置它们,但这似乎很浪费。

是否可以发送具有预定义属性的对象,然后以表单的形式更改其中的两个,但是当它从视图返回时仍保留不变的属性?

我唯一的另一种想法是创建隐藏的表单元素来保存模型的[in]绑定属性,但是如果我必须这样做,则最好在我认为的OnPostAsync方法中进行设置。< / p>

2 个答案:

答案 0 :(得分:1)

我没有看到您的页面或代码,但我刚刚在CodeProject上发表了一些帖子可能会有所帮助。看来您可能需要在.cshtml文件中使用一个form元素。您的[BindProperty]属性将使TenantSettingsModel值可用于UI中的元素。您可能会看(ASP.NET Core Razor Pages Using EntityFramework Core with Enums as Strings - Part II

我在这里使用Entity Framework Core。

在一个示例中,我在Razor页面的Edit.cshtml上编辑一个Customer对象([注意:我确实使用隐藏的输入将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中加载相关数据。 ([[使用EntityFramework Core和枚举作为字符串的ASP.NET Core剃刀页面-第III部分和ASP.NET Core Razor Pages Using EntityFramework Core with Enums as Strings - Part 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对象及其客户对象及其ProjectSkills的集合。每个ProjectSkill都有一个SkillTitle。另外,我将可用的SkillTitle对象的集合加载到选择/下拉列表中。选定的项目通过表单传递到OnPostAsync()。但是,只有一个隐藏的控件可以指示目标项目。

答案 1 :(得分:0)

我也面临类似的挑战,不确定我的方法是否正确。我不是在DIV中显示数据(待编辑),而是在TABLE中显示。我可以理解hidden属性如何更新行。就我而言,我在“编辑”页面上显示了多行,但是无法仅更新具有更新的行来更新数据库。

我的查看页面就是这样

<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" asp-for=@item.ID /> </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>

后面的代码是这个。字段在OnPostAsync方法中显示为0。

[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");
    }