asp.net core creating/updating a foreignkey

2019-08-17 04:58发布

问题:

I added to my "Todo" class a foreignKey to my "Pharmacy" class. When I add or edit a Todo, no Pharmacy can be linked (from a selectbox). Here's my model:

public class Todo
    {
        [Key]
        public int ID { get; set; }

        public Pharmacy Pharmacy { get; set; }
    }

public class Pharmacy
    {
        [Key]
        public int PharmacyID { get; set; }

        public string Name { get; set; }

        public string Pharmacist { get; set; }

        [DataType(DataType.PhoneNumber)]
        public int Phone { get; set; }

        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }

        public int NPA { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string Canton { get; set; }
    }

My code's listing to listing all Pharmacies on my Todo:

public class PharmacynamePageModel : PageModel
    {
        public SelectList PharmacyNameSL { get; set; }

        public void PopulatePharmacysDropDownList(ApplicationDbContext _context, object selectedPharmacy = null)
        {
            var query = (from p in _context.Pharmacy orderby p.Name select p).ToList();

            PharmacyNameSL = new SelectList(query, "PharmacyID", "Name", selectedPharmacy);
        }
    }

Well, at this step, i have this code on my HTML form:

<label asp-for="Todo.Pharmacy" class="control-label"></label>
                <select asp-for="Todo.Pharmacy" class="form-control"
                        asp-items="Model.PharmacyNameSL">
                    <option value="">-- Select a Pharmacy --</option>
                </select>
                <span asp-validation-for="Todo.Pharmacy" class="text-danger" />

and my PostAsync() into my create and edit controllers:

public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            var emptyTask = new Todo();

            if (await TryUpdateModelAsync(emptyTask, "Todo",  
                s => s.ID, s => s.OwnerID, 
                s => s.Title, s => s.Description,
                s => s.DueDate,
                s => s.Pharmacy,
                s => s.Priority))
            {
                emptyTask.Status = EnumStatus.Open;
                _context.Todo.Add(emptyTask);
                await _context.SaveChangesAsync();
                if (emptyTask.OwnerID != HttpContext.User.Identity.Name)
                {
                    LogVM.AddLog("Todos", $"{HttpContext.User.Identity.Name} attributed a new task to {emptyTask.OwnerID}.", _context);
                }
                return RedirectToPage("./Index");
            }

            PopulatePharmacysDropDownList(_context, emptyTask.Pharmacy);

            return RedirectToPage("./Index");
        }

All data are mapped/binded, but not the pharmacy field who's the value are always null.

Hope you can help me :).

Thanks per advance.

回答1:

On Post, Data Binding will bind the Select's "dataValueField" to the model's data member.

You are trying to map an entire object to the Select's selected item. You have mentioned that only the Pharmacy field is null - it is likely because from your provided code it looks like that's the only field you are probably trying to modify. The values for the other items are probably setup in the Page code itself (& not being data bound on Post).

I would suggest that you create a separate field for the selected "Pharmacy" item and bind that to the Select box.

Inside your PharmacynamePageModel class, create a pubic "bindable" property, like so:

 [BindProperty]
 public string SelectedPharmacy { get; set; }

And then on the Razor code, instead of binding to "Pharmacy", bind to "SelectedPharmacy" (in the asp-for attribute), like so:

                <select asp-for="SelectedPharmacy" class="form-control"
                        asp-items="Model.PharmacyNameSL">
                    <option value="">-- Select a Pharmacy --</option>
                </select>
                <span asp-validation-for="Todo.Pharmacy" class="text-danger" />

Now, on Form post, the selected Pharmacy Id should be available. It is up to you to make use of the Id as you wish.

Hope this works. If it does, please mark this as the answer.