如何为复杂的EF模型制作剃刀表格

时间:2018-09-06 19:13:48

标签: c# entity-framework entity-framework-6 asp.net-core-2.1 razor-pages

我开始怀疑我要问的问题是否甚至可能。但是应该。

MS示例严重缺乏我的追求,因此EF并非按照我的想法设计。 (BTW Scaffold for CRUD对于每个单独的表都很好用。但是它仅能进行表级创建。我想要一些将关系作为对象进行管理的东西。)

public class ContactPhone
{
    public ContactPhone(ContactPhone contactPhone)
    {
        Id = contactPhone.Id;
        ContactId = contactPhone.ContactId;
        ContactPhoneTypeId = contactPhone.ContactPhoneTypeId;
        Number = contactPhone.Number;
    }

    //private ContactPhone contactPhone;

    public ContactPhone()
    {
    }

    //public ContactPhone(ContactPhone contactPhone)
    //{
    //    this.contactPhone = contactPhone;
    //}

    public int Id { get; set; }

    public int ContactId { get; set; }
    public virtual Contact Contact { get; set; }

    public int ContactPhoneTypeId { get; set; }
    public virtual ContactPhoneType ContactPhoneType { get; set; }

    public string Number { get; set; }
}


public class Contact
{
   public  Contact()
    {
        Phones = new List<ContactPhone>();
    }
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }

    public int LocationAddressId { get; set; }
    public LocationAddress LocationAddress { get; set; }

    public int UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual SCPI_site_User User { get; set; }

    //public ICollection

    public List<ContactPhone> Phones { get; set; }
}

我知道这是错误的,但它确实可行...我的假设是我的联系人是持久性的,并且在Razor页面之间来回传递,但是事实并非如此。

            public class CreateModel : PhoneTypesPageModel
            {
                private readonly SCPI_Site.Areas.SCPI_SiteContext _context;

                public CreateModel(SCPI_Site.Areas.SCPI_SiteContext context)
                {
                    _context = context;
                }
                [TempData]
                public string Message { get; set; }

                [BindProperty]
                public Contact Contact { get; set; }

                [BindProperty]
                public ContactPhone ContactPhone { get; set; }

                //public bool HasPhones => Contact.Phones.Count > 0;

                public IActionResult OnGet()
                {
                    PopulatePhoneTypeDropDownList(_context);
                    int userID = User.Identity.GetUserId<int>();

                    if (Contact == null)
                    {
                        Contact = new Contact();
                    }
                    if (ContactPhone == null)
                    {
                        Contact = new Contact();
                    }

                    Contact.UserId = userID;
                    ViewData["UserId"] = userID;          
                    return Page();
                }

                public async Task<IActionResult> OnPostAsync(string submit)
                {
                    int userID = User.Identity.GetUserId<int>();
                    Contact.UserId = userID;        

                    switch (submit)
                    {
                        case "AddPhone":
                            // (failed attempt) _context.ContactPhone.Add(ContactPhone);
                            Contact.Phones.Add(new ContactPhone(ContactPhone));
                            ContactPhone.Number = "";
                            return Page();


                        default:
                            //if (!ModelState.IsValid)
                            //{
                            //    return Page();
                            //}

                            _context.Contact.Add(Contact);
                            await _context.SaveChangesAsync();
                            Message = "Contact Created!";

                            return RedirectToPage("./Index");
                    }

                }
            }
        }

HTML:

    @page

    @model SCPI_Site.Areas.ContactModel.Pages.Contacts.CreateModel

    @{
        //Layout = "~/Views/Shared/_AdminLayout.cshtml";
        ViewData["Title"] = "Create";
    }
    <div class="col">
        <h4>Contact</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="Contact.UserId" />
                    <div class="row">
                        <div class="form-group col-md-6">
                            <label asp-for="Contact.FirstName" class="control-label"></label>
                            <input asp-for="Contact.FirstName" class="form-control" />
                            <span asp-validation-for="Contact.FirstName" class="text-danger"></span>
                        </div>
                        <div class="form-group col-md-6">
                            <label asp-for="Contact.LastName" class="control-label"></label>
                            <input asp-for="Contact.LastName" class="form-control" />
                            <span asp-validation-for="Contact.LastName" class="text-danger"></span>
                        </div>
                    </div>

                    <div class="form-group">
                        <label asp-for="Contact.Email" class="control-label"></label>
                        <input asp-for="Contact.Email" class="form-control" />
                        <span asp-validation-for="Contact.Email" class="text-danger"></span>
                    </div>

                    <div class="form-group">
                        <label asp-for="Contact.LocationAddress.Address" class="control-label"></label>
                        <input asp-for="Contact.LocationAddress.Address" class="form-control" />
                        <span asp-validation-for="Contact.LocationAddress.Address" class="text-danger"></span>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-4">
                            <label asp-for="Contact.LocationAddress.City" class="control-label"></label>
                            <input asp-for="Contact.LocationAddress.City" class="form-control" />
                            <span asp-validation-for="Contact.LocationAddress.City" class="text-danger"></span>
                        </div>
                        <div class="form-group col-md-4">
                            <label asp-for="Contact.LocationAddress.State" class="control-label"></label>
                            <input asp-for="Contact.LocationAddress.State" class="form-control" />
                            <span asp-validation-for="Contact.LocationAddress.State" class="text-danger"></span>
                        </div>
                        <div class="form-group col-md-4">
                            <label asp-for="Contact.LocationAddress.PostalCode" class="control-label"></label>
                            <input asp-for="Contact.LocationAddress.PostalCode" class="form-control" />
                            <span asp-validation-for="Contact.LocationAddress.PostalCode" class="text-danger"></span>
                        </div>
                    </div>

                    @if (Model.Contact.Phones != null)
                    {
                        <hr />
                        <table class="table">
                            <thead>
                                <tr>
                                    <th>
                                        Type
                                        @*@Html.DisplayNameFor(model => model.Contact.Phones[0].ContactPhoneType)*@
                                    </th>
                                    <th>
                                        Number
                                        @*@Html.DisplayNameFor(model => model.Contact.Phones[0].Number)*@
                                    </th>
                                    <th></th>
                                </tr>
                            </thead>
                            <tbody>
                                @if (Model.Contact.Phones != null)
                                {
                                    @foreach (var item in Model.Contact.Phones)
                                    {
                                        <tr>
                                            <td>
                                                @Html.DisplayFor(modelItem => item.ContactPhoneType.Id)
                                            </td>
                                            <td>
                                                @Html.DisplayFor(modelItem => item.Number)
                                            </td>
                                            <td>
                                                <a asp-page="../ContactPhones/Edit" asp-route-id="@item.Id">Edit</a> |
                                                <a asp-page="../ContactPhones/Details" asp-route-id="@item.Id">Details</a> |
                                                <a asp-page="../ContactPhones/Delete" asp-route-id="@item.Id">Delete</a>
                                            </td>
                                        </tr>
                                    }
                                }
                            </tbody>
                        </table>
                    }
                    <div class="form-group">
                        <input type="submit" value="Create" class="btn btn-default" />
                    </div>

                    <div id="pay-invoice" class="card">
                        <div class="card-body">
                            <div class="card-title">
                                <input type="hidden" id="x_card_num" name="x_card_num" value="">
                                @*<partial name="../ContactPhones/Index" model=@Model />*@


                                @*First name:
                                <input type="text" name="A" value="<%= ViewData[" A"] %>" />
                                <br />
                                Last name:
                                <input type="text" name="B" value="<%= ViewData[" B"] %>" />
                                <br />
                                <input type="submit" value="Insert" />
                                <button type="submit" name="submit" value="add"><span class="glyphicon glyphicon-plus"></span>Add another</button>*@



                                <input type="hidden" asp-for="ContactPhone.ContactId" />
                                <div class="row">
                                    <div class="form-group col-md-7">
                                        <label asp-for="ContactPhone.Number" class="control-label"></label>
                                        <input asp-for="ContactPhone.Number" class="form-control" />
                                        <span asp-validation-for="ContactPhone.Number" class="text-danger"></span>
                                    </div>
                                    <div class="form-group col-md-5">
                                        <label asp-for="ContactPhone.ContactPhoneType" class="control-label"></label>
                                        <select asp-for="ContactPhone.ContactPhoneTypeId" class="form-control"
                                                asp-items="@Model.PhoneTypeSL">
                                            @*<option value="">-- Select Type --</option>*@
                                        </select>
                                        <span asp-validation-for="ContactPhone.ContactPhoneTypeId" class="text-danger" />
                                    </div>
                                </div>

                                <button type="submit" name="submit" value="AddPhone" class="btn btn-primary"><span class="fa fa-plus"> </span>  Add Phone Number</button>

                                @*<a asp-area="ContactsModel" asp-page="/ContactPhones/Create"> Add Phone Number</a>*@
                            </div>
                        </div>
                    </div>

                    <p>

                        @*    <a asp-page="Create">Create New</a>*@
                    </p>

                    @*@Html.Hidden("Contact.UserId")   This breaks the validation*@
                    @*<div class="form-group">
                            <label asp-for="Contact.UserId" class="control-label"></label>
                            <select asp-for="Contact.UserId" class="form-control" asp-items="ViewBag.UserId"></select>
                        </div>*@




                </form>
            </div>
        </div>

        <div>
            <a asp-page="Index">Back to List</a>
        </div>
    </div>
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

创建:

鉴于这个小模型,我如何创建一个剃须刀页面,该页面将电话记录添加到Contact对象并捕获Contact Object数据,并通过一个Save呼叫创建整个模型。 (管理按键等)

现在我在这里可能不合时宜,但是这种情况正是我对ORM的期望。坦白说,我不确定为什么有人会构建EF而没有提供这种功能。但是可能我缺少了一些东西,因此我多次翻阅了MS文档,以寻找线索。

但是它在Django中是这样的;)

如果甚至有这样一种类型的操作示例与同一位客户都不相同,那么我将不胜感激。

谢谢 CB

1 个答案:

答案 0 :(得分:1)

如果要将项目绑定到某种类型的集合的属性,则需要将索引器添加到表单字段的名称或传递给taghelper的asp-for属性的表达式的开头,与0

这是一个更简单的模型:

public class Order
{
    public int OrderId { get; set; }
    public string Customer { get; set; }
    public List<OrderItem> Items { get; set; }
}

public class OrderItem
{
    public int OrderItemId { get; set; }
    public string Item { get; set; }
    public decimal Price { get; set; }
}

这是PageModel:

public class CreateModel : PageModel
{
    [BindProperty]
    public Order Order { get; set; }

    public void OnPost()
    {

    }
}

这是表格:

@page
@model CreateModel
@{
}

<form method="post">
    <input asp-for="Order.Customer" /><br />
    <input asp-for="Order.Items[0].Item" /><br/>
    <input asp-for="Order.Items[0].Price" />
    <input type="submit"/>
</form>

这就是您所需要的。表单中的值将自动绑定到标有Order属性的[BindProperty]属性。如果将其传递给EF,它将创建并保存订单,然后使用ID创建并保存OrderItem。如果要允许用户创建更多项目,只需为每个项目将索引器增加1

<form method="post">
    <input asp-for="Order.Customer" /><br />
    @for (var i = 0; i < 5; i++)
    {
    <input asp-for="Order.Items[i].Item" /><br/>
    <input asp-for="Order.Items[i].Price" />
    }
    <input type="submit"/>
</form>

参考:https://www.learnrazorpages.com/razor-pages/model-binding#binding-complex-collections