Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In your POST controller action you forgot to populate the ViewCrap (oops, I meant ViewBag) before returning the view:</p> <pre><code>&lt;HttpPost()&gt; Function Create(job As Job) As ActionResult If ModelState.IsValid Then ... End If ' Here you must populate the ViewCrap before returning the view the same ' way you did in your GET action because your view depend on it Dim BillQuery = From s In db.Bills Select s ViewBag.BillId = New SelectList(BillQuery.ToList(), "BillId", "BillDate") Return View(job) End Function </code></pre> <p>But I would hyper strongly recommend you to use view models and forget about the existence of the ...... (the word that I don't want to pronounce).</p> <hr> <p>UPDATE:</p> <p>Now let's look at the correct way to implement this (which is by using view models). A view model is a class that you should define for each of your views and which will represent its specific requirements. So from what you have said in the comments section to my answer you want to have a dropdown list in your view where the user has to select a bill from a dropdown and which is required.</p> <p>So let's roll the view model:</p> <pre><code>public class JobViewModel { [Required(ErrorMessage = "Please select a bill")] [Display(Name = "Bill")] public int? SelectedBillId { get; set; } public IEnumerable&lt;SelectListItem&gt; Bills { get { return db.Bills.ToList().Select(x =&gt; new SelectListItem { Value = x.BillId.ToString(), Text = x.BillDate.ToString() }); } } public int CustomerId { get; set; } ... here you could put any other properties that you want to display on the view, things like JobId, ... } </code></pre> <p>then we define our controller with the 2 actions:</p> <pre><code>public ActionResult Create(int id) { var model = new JobViewModel { CustomerId = id }; return View(model); } [HttpPost] public ActionResult Create(JobViewModel model) { if (ModelState.IsValid) { // Using AutoMapper here to map between the domain model // and the view model (http://automapper.org/) var job = Mapper.Map&lt;JobViewModel, Job&gt;(model); // Now call your service layer to do the necessary processings // on this job domain model including saving the job and sending // messages and stuff. This avoids polluting your controller with // business logic code which belongs to your service layer ServiceLayer.ProcessJob(job); return RedirectToAction("AddService", "RequestedService", new { id = job.JobId }); } return View(model); } </code></pre> <p>and finally you will have a corresponding view which will be strongly typed to the view model:</p> <pre><code>@model JobViewModel @using (Html.BeginForm()) { &lt;div&gt; @Html.LabelFor(x =&gt; x.SelectedBillId) @Html.DropDownListFor(x =&gt; x.SelectedBillId, Model.Bills, "-- select --") @Html.ValidationMessageFor(x =&gt; x.SelectedBillId) &lt;/div&gt; ... some other input fields &lt;p&gt;&lt;button type="submit"&gt;OK&lt;/button&gt;&lt;/p&gt; } </code></pre> <hr> <p>And now, as promised in the comments section let me show what I dubbed the absolute <em>pornographic</em> approach to solve this and which if you implemented in your application I will have to ask you to no longer come back and ask any ASP.NET MVC related question on StackOverflow :-)</p> <p>The <em>pornographic</em> approach consisted into manually inserting an item with id = 0 and text = empty string into the beginning of the list and then inside the controller verifying if the selected id equals 0 in order to check whether the model is valid or not:</p> <p>So in your GET action:</p> <pre><code>Function Create(id As Integer) As ViewResult ViewBag.id = id Dim job As Job = New Job job.CustomerId = id job.JobAmount = 0 job.JobDate = Date.Now() job.JobStatus = "Active" Dim Bills = db.Bills.ToList().Select(Function(s) New SelectListItem With { .Value = s.BillId.ToString(), .Text = s.BillDate.ToString() }) Bills.Insert(0, New SelectListItem With { .Value = "0", .Text = "" }) ViewBag.BillId = Bills Return View(job) End Function &lt;HttpPost()&gt; Function Create(job As Job, BillId as Integer) As ActionResult If BillId &gt; 0 Then db.Jobs.Add(job) db.SaveChanges() Dim customer As Customer = db.Customers.Find(job.CustomerId) Dim customerNumber As String = customer.CustCellphone.ToString() Dim messageSender As SendMessage = New SendMessage Dim smsMessage As String = "LAUNDRY: Job Number " &amp; job.JobId &amp; " has been booked in. You will be notified when individual services within it are ready for collection." messageSender.SendMessage(smsMessage, customerNumber) Dim url As String = "/RequestedService/AddService/" + job.JobId.ToString() Return Redirect(url) End If ModelState.AddModelError("BillId", "Please select a bill") Return View(job) End Function </code></pre> <p>and inside the view:</p> <pre><code>@Html.DropDownList("BillId") </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload