2

だから私はウェブアプリケーションに取り組んでいて、数週間立ち往生している新しい課題に遭遇しました. アプリケーションとデータ モデル、および望ましい最終結果に関する背景情報を提供します。

アプリの基本情報と問題の状況: 私のアプリは、造園請負業者が事業運営の管理を支援するために使用できるツールとして機能することを目的としています。私のアプリは、アカウントを作成できる場所を提供し、すべての顧客情報 (「クライアント」データ モデル) と、各クライアントに対して行っている仕事に関する情報 (「ジョブ」データ モデル) を入力します。 . クライアントとジョブの間には 1 対多の関係があります (1 つのクライアントが複数のジョブを持つことができますが、特定のジョブに対してクライアントは 1 つだけです)。

背景: 「クライアント」と「ジョブ」という 2 つの単純なデータ モデルがあります。私のアプリは、ASP.net MVC3 フレームワークで構築されています。Entity Framework のスキャフォールディング メカニズムを使用して、これらのデータ モデル (作成、読み取り、更新、削除) ごとに基本的な CRUD ビューを作成しました。ほとんどの場合、これは素晴らしいことです (新しいクライアントとジョブを作成し、既存のものを簡単に編集できます)。

ビジネス上の問題: アプリケーションで新しいジョブのバッチ作成を許可する必要があります。ユーザー (造園請負業者) が、その日に完了したすべての草刈り作業を入力できるようにしたいと考えています。そのため、このプロセスのビューに、すべてのアクティブなクライアントをテーブルに入力させたいと思います - それぞれの行の横にチェックボックスがあります。次に、ユーザーが新しい仕事をした(芝生を刈った)各クライアントのボックスをチェックして、フォームを送信(完了した仕事を入力)できるようにしたいと思います。その結果、これらのクライアントごとに新しい仕事が作成されます.

技術的な問題: コントローラーでカスタム ViewModel を作成し、ビューに送信する必要があると思います。ViewModel は、現在アクティブなクライアントに基づいて作成された新しいジョブのリストです。次に、ビューでは、チェックボックスに値として Client_ID (クライアントの一意の識別子) を含めることができます (これは ViewModel の一部になります。ユーザーがフォームを送信すると、ビューは ViewModel をコントローラーに返します。次に、コントローラーViewModel ジョブのリストを調べて、チェックボックスがオンになっている ViewModel ジョブごとに新しいジョブを作成できます。

それで、私の質問は、コントローラーを使用して次のことを行うにはどうすればよいかということです。2.)どうすればそれをビューに渡すことができますか? 3.) コントローラーに戻ったら、どのようにリストを反復処理し、それに応じて他のデータ モデルを変更できますか (新しい「ジョブ」アイテムを作成します)?

カスタム ViewModel を作成しました。これには、新しいジョブ エントリを作成するために必要なクライアントとジョブの属性 (クライアント名、クライアント アドレス、クライアント ID、ジョブ メモ、クルー、クルー サイズ、ジョブの時間、完了を示すチェックボックスなど) が含まれています。 .)。ユーザーが、アクティブなクライアントである芝刈りをしている 50 のクライアントを持っているとします。50 行の ViewModel を作成したいと思います (芝刈りを行う可能性のある各クライアントを表すため)。次に、それをビューに送信し、芝生が刈られたかどうかを示すチェックボックスで表示します。モデルがビューに戻ると、コントローラーはチェックボックスにチェックが入っている行を取得し、そのテーブルに新しい「ジョブ」行を作成します。

提供できる支援を前もって感謝します。これはおそらく多くの人にとって簡単なことだと思います。C# と MVC3 は初めてです。

更新: ここに私のコードがあります -

ジョブモデル

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace LawnTracker.Models
{
    public class Job
    {
        [Key]
        public int Job_ID { get; set; }
        public int Client_ID { get; set; }
        public int Account_ID { get; set; }
        public string Name { get; set; }
        public string Location { get; set; }
        public string Notes { get; set; }
        public string SvcRoute { get; set; }
        public string Service { get; set; }
        public string Date { get; set; }
        public double SvcPriceOverride { get; set; }
        public float SvcQty { get; set; }
        public string UofM { get; set; }
        public bool Invoiced { get; set; }
        public string Crew { get; set; }
        public int TechCount { get; set; }
        public string TimeStart { get; set; }
        public string TimeFinish { get; set; }
        public double TimeSpent { get; set; }
        public string Image1 { get; set; }
        public string Image2 { get; set; }
        public string Image3 { get; set; }
        public double MulchUsed { get; set; }
        public double FertUsed { get; set; }
        public double HerbUsed { get; set; }
        public string NextDue { get; set; }

    }


}

私の MowingJobViewModel モデル -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace LawnTracker.Models
{
    public class MowingJobViewModel
    {
        public int Client_ID { get; set; }

        public bool Completed { get; set; }

        public string Name { get; set; }

        public string Street { get; set; }

        public string City { get; set; }

        public double SvcPriceOverride { get; set; }

        public string UofM { get; set; }

        public int SvcQty { get; set; }

        public string Notes { get; set; }

        public string Date { get; set; }

        public string Crew { get; set; }

        public int TechCount { get; set; }

        public string SvcRoute { get; set; }

        public string Schedule { get; set; }
    }
}

そして私の JobController -

 // GET: /Job/CreateMowing

        public ActionResult CreateMowing(string route = "", string sched = "")
        {
            List<SelectListItem> listItems = new List<SelectListItem>();
            listItems.Add(new SelectListItem()
            {
                Value = "Lump Sum",
                Text = "Lump Sum"
            });
            listItems.Add(new SelectListItem()
            {
                Value = "Hours",
                Text = "Hours"
            });


            ViewBag.Units = new SelectList(listItems, "Value", "Text");
            ViewBag.Routes = db.Clients.Select(r => r.SvcRoute).Distinct();
            ViewBag.Sched = db.Clients.Select(r => r.MowSched).Distinct();

            var model = from r in db.Clients
                        orderby r.SvcRoute
                        where (r.Mowing == true) &&
                        (r.Status == "Active") &&
                        (r.SvcRoute == route || (route == "")) &&
                        (r.MowSched == sched || (sched == "")) 
                        select r;
            if (model.Count() > 0)
            {
                ViewBag.total = model.Select(r => r.MowPrice).Sum();
            }
            else
            {
                ViewBag.total = 0.00;
            }

           /* Build a list of MowingJobViewModel objects based on the above defined list of clients
            * who are subscribed to mowing and active. This will enable batch entry for new jobs done.
            * This list of MowingJobViewModel objects will be sent to the client after a HTTP GET
            * request for the CreateMowing view.  The user will be able to check boxes associated
            * with each client in the client list.  When the form is submitted, the controller
            * receives the model back with the updated information (completed, notes, etc.) about
            * each job.  Then the controller must update the jobs table, adding the new jobs based on 
            * the view model returned from the view / client.
            * 
            */

            //Create a new list of MowingJobViewModel objects
             IEnumerable<MowingJobViewModel> mjList = new List<MowingJobViewModel>();

            //iterate through the list of clients built from earlier (in model)...
             foreach (var item in model)
             {  
             //create new MowingJobViewModel object MJ and add it to the list
             mjList.Add(new MowingJobViewModel()
             {
               Client_ID = item.Client_ID,
               Completed = false,
               Name = (item.FirstName + " " + item.LastName),
               Street = item.Address1,
               City = item.City,
               SvcPriceOverride = item.MowPrice,
               UofM = "Lump Sum",
               SvcQty = 1,
               Notes = "",
               Date = "",
               Crew = "",
               TechCount = 2,
               SvcRoute = item.SvcRoute,
               Schedule = item.MowSched,
              });

             }

             return View(mjList);

             }

**I don't have my view ("CreateMowing.cshtml") worked out correctly, but here is what I have-**

@model IEnumerable<LawnTracker.Models.MowingJobViewModel>

@{
    ViewBag.Title = "Enter Mowing Jobs";
}

<h2>Enter Mowing Jobs</h2>

<div style="float: left; clear:both; width: 100%;">
    <b>Total Jobs: @Html.Encode(Model.Count())</b><br />
    <b>Total Revenue: $@Html.Encode(ViewBag.total)</b><br /><br />
</div>
<p></p>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

<div style="float: right; clear:both; width: 100%;">
     @using (Html.BeginForm("CreateMowing", "Job", FormMethod.Get)) 
    {
    <table>
    <tr>
        <th></th>

        <th>
            Route
        </th>

        <th>Schedule</th>
        <th></th>
    </tr>
    <tr>
        <td>
            Show:
        </td>

        <td>
            @Html.DropDownList("route", new SelectList(ViewBag.Routes), "--ALL--")            
        </td>

        <td>
            @Html.DropDownList("sched", new SelectList(ViewBag.Sched), "--ALL--")
        </td>
        <td>            
            <input type="submit" value="Filter" />
        </td>
    </tr>
</table><br /><br />

    }
</div>

<table>
    <tr>
        <th>
            Completed
        </th>
        <th>
            First Name
        </th>
        <th>
            Last Name
        </th>
        <th>
            Street
        </th>

        <th>
            City
        </th>

        <th>
            Service Route
        </th>
        <th>
            Price
        </th>

        <th>
            Units
        </th>

        <th>
            Qty
        </th>
        <th>
            Notes
        </th>

        <th>
            Schedule
        </th>

    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            <input type="checkbox" name="invoiced" value="@item.Client_ID" >
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Address1)
        </td>

        <td>
            @Html.DisplayFor(modelItem => item.City)
        </td>

        <td>
            @Html.DisplayFor(modelItem => item.SvcRoute)
        </td>

        <td>
            @Html.DisplayFor(modelItem => item.MowPrice)
        </td>

        <td>

        </td>

        <td>

        </td>
        <td>

        </td>

        <td>
            @Html.DisplayFor(modelItem => item.MowSched)
        </td>

     </tr>
}

</table>


<div>
    <br />
    @Html.ActionLink("Back to List", "Index")
</div>
4

1 に答える 1

0

ジョブの作成時に、特定のクライアントの表示属性/データ入力フィールドを含むビュー モデルを作成しました。名前を付けてくれなかったので、 と呼びますNewJobEntryList<NewJobEntry>ご想像のとおり、一度に作成できる可変数の新しいジョブを表すタイプのプロパティを持つビューモデルが必要になりました。

コントローラーがリストに入力し、NewJobEntry各クライアントのインスタンスを追加します。

リストを含むモデルが提供されると、ビューはリストを列挙し、それぞれの行を生成できますNewJobEntry

データがコントローラーに戻されると、既定の ASP.NET MVC バインダーはリストを処理できますが、いくつかの癖があります。デフォルトのバインダーは、フィールド名に連続したインデックスがある限り、リスト内のオブジェクトを自動的にハイドレートします。これらのインデックスが正しく生成されるようにするには、シーケンシャル インデックスを持つビューでラムダ式を使用してバインドする必要があります。

Html.CheckboxFor(model => model.JobList[i].IsSelected)

リストを列挙するときforは、ループの代わりにループを使用することを検討してください。foreach

また、チェックされていないチェックボックスはコントローラーに送信されるポストデータに実際には表示されないため、チェックボックスにも注意する必要があります。投稿データで送信されたインデックスがシーケンシャルでなくなる可能性があるため、バインディングが壊れます (チェックされていないチェックボックスがある場所にはギャップが生じます)。したがって、クライアント ID の非表示フィールドを含めることをお勧めします。このように、投稿データには常に、各リスト エントリに適切な連続インデックスを持つ少なくとも 1 つのフィールドが含まれます。

Html.HiddenFor(model => model.JobList[i].ClientId)

これで、投稿データは次のようになります。

JobList_0_IsSelected=true
JobList_0_ClientId=12345
JobList_1_ClientId=12346
JobList_2_IsSelected=true
JobList_2_ClientId=12347

デフォルトのバインダーがこれを処理し、リストを再構築します。クライアント ID の非表示フィールドがないと、インデックス1が失われ、デフォルトのバインダーがリストを正しく再構築しないことに注意してください。

それが役立つことを願っています!

于 2012-11-14T05:11:51.927 に答える