Создать запись с помощью списка моделей

Я пытаюсь создать счет-фактуру. У меня две модели, Invoice и InvoiceItems.

Я могу вставлять, используя жестко закодированные значения, но я хочу иметь возможность использовать TextBoxes для создания счета на лету. Как вставить запись, которая берет данные для счета и динамические данные из элементов счета и вставляет их в обе таблицы, используя одно и то же представление? Я бы хотел, чтобы в конечном итоге появилась кнопка добавить еще, с помощью которой я мог бы оставаться на той же странице и продолжать добавлять товары в один и тот же счет. Вы можете увидеть, что я пробовал до сих пор ниже.

Модель счета:

public class Invoice
{
    [Key]
    public int InvoiceId { get; set; }
    public int ClientId { get; set; }
    [Display(Name = "Amount")]
    public decimal Amount { get; set; }
    [Display(Name = "Invoice Creation Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime CreationDate { get; set; }
    [Display(Name = "Invoice Due Date")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime DueDate { get; set; }
    [Display(Name = "Notes")]
    public string InvoiceNotes { get; set; }

    public List<InvoiceDetails> InvoiceDetails { get; set; } 
    public List<Clients> Clients { get; set; } 
}

Модель InvoiceItem:

public class InvoiceDetails
{
    [Key]
    public int InvoiceDetailsId { get; set; }
    public int InvoiceId { get; set; }
    [DisplayName("Item Name")]
    public string Name { get; set; }
    [DisplayName("Item Note")]
    public string Note { get; set; }
    [DisplayName("Qty")]
    public decimal? Quantity { get; set; }
    [DisplayName("Rate/Hour")]
    public decimal? Price { get; set; }
    [DisplayName("Item Total")]
    public decimal? Total { get; set; }
}

Контролер счетов:

private NovaDb _db = new NovaDb();
public ActionResult InvoiceInformation()
    {
        var invoice = new Invoice();

        invoice.InvoiceDetails = new List<InvoiceDetails>();

        return View(invoice);
    }

    [HttpPost]
    public ActionResult InvoiceInformation(Invoice model)
    {
        if (ModelState.IsValid)
        {
            var invoices = new Invoice()
            {
                Amount = model.Amount,
                CreationDate = model.CreationDate,
                DueDate = model.DueDate,
                InvoiceNotes = model.InvoiceNotes,
                InvoiceId = model.InvoiceId,
                ClientId = model.ClientId                    
            };

            _db.Invoices.Add(invoices);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(model);
    }

Просмотр счета:

@model NovaFinancial.Models.Invoice

@{
ViewBag.Title = "InvoiceInformation";
}

<h2>InvoiceInformation</h2>

@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)

<fieldset>
    <legend>Invoice</legend>

    @Html.HiddenFor(model => model.InvoiceId)

    <div class="editor-label">
        @Html.LabelFor(model => model.ClientId)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ClientId)
        @Html.ValidationMessageFor(model => model.ClientId)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Amount)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Amount)
        @Html.ValidationMessageFor(model => model.Amount)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.CreationDate)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.CreationDate)
        @Html.ValidationMessageFor(model => model.CreationDate)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.DueDate)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.DueDate)
        @Html.ValidationMessageFor(model => model.DueDate)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.InvoiceNotes)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.InvoiceNotes)
        @Html.ValidationMessageFor(model => model.InvoiceNotes)
    </div>

    <div>
        <table>
            <tr>
                <th>Name</th>
                <th>Notes</th>
                <th>Qty</th>
                <th>Price</th>
                <th>Total</th>
            </tr>
            @for (int i = 0; i < Model.InvoiceDetails.Count; i++)
            {
                @Html.HiddenFor(m=>m.InvoiceDetails[i].Name)    
                @Html.HiddenFor(m=>m.InvoiceDetails[i].Note) 
                @Html.HiddenFor(m=>m.InvoiceDetails[i].Quantity) 
                @Html.HiddenFor(m=>m.InvoiceDetails[i].Price) 
                @Html.HiddenFor(m=>m.InvoiceDetails[i].Total) 
                <tr>
                    <td>@Html.DisplayFor(m=>m.InvoiceDetails[i].Name) | @Html.TextBoxFor(m=>m.InvoiceDetails[i].Name)</td>
                    <td>@Html.DisplayFor(m=>m.InvoiceDetails[i].Note) | @Html.TextBoxFor(m=>m.InvoiceDetails[i].Note)</td>
                    <td>@Html.DisplayFor(m=>m.InvoiceDetails[i].Quantity) | @Html.TextBoxFor(m=>m.InvoiceDetails[i].Quantity)</td>
                    <td>@Html.DisplayFor(m=>m.InvoiceDetails[i].Price) | @Html.TextBoxFor(m=>m.InvoiceDetails[i].Price)</td>
                    <td>@Html.DisplayFor(m=>m.InvoiceDetails[i].Total) | @Html.TextBoxFor(m=>m.InvoiceDetails[i].Total)</td>
                </tr>
            }                
        </table>
    </div>

    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
}

person C.Coggins    schedule 30.09.2014    source источник
comment
Итак, какой у вас вопрос?   -  person Tobias    schedule 30.09.2014
comment
Просто хотел проверить, добились ли вы какого-либо прогресса в решении вашей проблемы. Меня это интересует, поэтому сегодня я потратил немного времени, работая над этим. Я могу создать счет с одним элементом, но все еще пытаюсь выяснить, как я могу передать несколько элементов. Я знаю, что передача входных данных формы с использованием одного и того же имени дает массив, и я чувствую, что он может содержать ключ.   -  person CM Kanode    schedule 03.10.2014


Ответы (1)


Я разработал «решение», которое может быть не самым лучшим, но оно работает. Вам все равно придется дополнять код, чтобы сделать его более надежным, но общая структура существует.

С вашей точки зрения, оставьте во всех текстовых полях для деталей счета (имя, количество, цена) одно и то же значение атрибута имени, но сохраните уникальный идентификатор. Я использовал немного jQuery и JavaScript для создания дополнительных строк по мере необходимости для каждой кнопки, которую нажимал пользователь. Например,

<input type="text" name="Name" id="Name"> <!--first line item for Item Name-->
<input type="number" name="Quantity" id="Quantity"> <!--first for Quanitity -->

<input type="text" name="Name" id="Name2"> <!--second line item for Item Name-->
<input type="number" name="Quantity" id="Quantity2"> <!-- second for Quanitity -->

Значения для строк InvoiceDetail будут передаваться обратно на сервер в виде строк с разделителями-запятыми (лучше убедиться, что в именах ваших товаров нет запятых!). На стороне сервера

var Names = Request["Name"]; // this would yield something like "Labor,Parts"

В контроллере вам нужно разобрать строки на массивы и создать из них экземпляры вашего InvoiceDetail. Я написал частный метод для разделения строк и возврата списка объектов InvoiceDetail методу действия. Ответственность за проверку этих данных лежит на вас: проверка требуется как на стороне клиента, так и на стороне сервера.

Я провел несколько экспериментов. Вы можете увидеть весь код здесь: http://mefixme.blogspot.com/2014/10/aspnet-mvc-how-to-add-model-with.html

Я надеюсь, что это поможет вам.

person CM Kanode    schedule 03.10.2014